diff --git a/admin/app/admin/ars.rb b/admin/app/admin/ars.rb index e150e4401..0b8c4def0 100644 --- a/admin/app/admin/ars.rb +++ b/admin/app/admin/ars.rb @@ -2,4 +2,29 @@ ActiveAdmin.register JamRuby::Ars, :as => 'Ars' do menu :label => 'NAS', :parent => 'Operations' + + form do |f| + f.inputs 'Controls' do + f.input :active + f.input :beta + end + f.inputs 'Meta' do + f.input :name + f.input :provider + f.input :id_int + f.input :ip + f.input :username + f.input :password, as: :string + f.input :port + f.input :continent + f.input :country, as: :string + f.input :city + f.input :subdivision + f.input :latitude + f.input :longitude + end + f.actions + end + + end diff --git a/admin/app/admin/dashboard.rb b/admin/app/admin/dashboard.rb index e4c5ff6db..d5d4af4a9 100644 --- a/admin/app/admin/dashboard.rb +++ b/admin/app/admin/dashboard.rb @@ -8,11 +8,9 @@ ActiveAdmin.register_page "Dashboard" do span "JamKazam Administration Portal" small ul do li link_to "Users", admin_users_path + li link_to "K12 Users", admin_users_path("q[import_source_equals]": "K12") li link_to "Teachers", admin_teachers_path - li link_to "Onboarding Management", admin_onboarder_managements_path - li link_to "Onboarding Settings", admin_onboarders_path - li link_to "Lesson Sessions", admin_lesson_sessions_path - li link_to "Slow Lesson Responses", admin_slow_responses_path + li link_to "Upload School Users", admin_schooluseruploads_path end end diff --git a/admin/app/admin/jam_ruby_users.rb b/admin/app/admin/jam_ruby_users.rb index 38c61b7da..a71f1f13e 100644 --- a/admin/app/admin/jam_ruby_users.rb +++ b/admin/app/admin/jam_ruby_users.rb @@ -11,6 +11,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do filter :jamuser_full_name_or_email_cont, label: 'Name Or Email', as: :string filter :created_at filter :updated_at + filter :import_source includes :purchased_jam_tracks, :jam_track_rights => :jam_track, :taken_lessons => :music_session, :taught_lessons => :music_session @@ -22,6 +23,19 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do end + member_action :quick_reset, :method => :get do + resetting_to = 'jellyandjam123' + resource.change_password(resetting_to, resetting_to) + resource.save + redirect_to :back, {notice: "Reset password to #{resetting_to }"} + end + + member_action :create_reset, :method => :get do + reset_url = resource.create_tokened_reset_url + redirect_to :back, {notice: "Reset password url created: #{reset_url}"} + end + + show do |user| panel "Common" do @@ -73,6 +87,25 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do end end + row "Quick Password Reset" do |user| + span do + link_to("Reset Password to jellyandjam123", quick_reset_admin_user_path(user.id), :data => {:confirm => 'Reset password to jellyandjam123 ?'}) + end + end + + row "Send Password Reset Email" do |user| + span do + Rails.application.config.external_root_url + "/request_reset_password" + end + end + + row "Password Reset URL" do |user| + span do + link_to("Create Reset URL", create_reset_admin_user_path(user.id), :data => {:confirm => 'Are you sure?'}) + end + end + + row :jamclass_credits row :via_amazon row "Web Profile" do @@ -267,6 +300,7 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do @user.last_name = params[:jam_ruby_user][:last_name] @user.state = params[:jam_ruby_user][:state] @user.city = params[:jam_ruby_user][:city] + @user.is_platform_instructor = params[:jam_ruby_user][:is_platform_instructor] @user.gifted_jamtracks = params[:jam_ruby_user][:gifted_jamtracks] diff --git a/admin/app/admin/school_user_uploads.rb b/admin/app/admin/school_user_uploads.rb new file mode 100644 index 000000000..30ed6c6c6 --- /dev/null +++ b/admin/app/admin/school_user_uploads.rb @@ -0,0 +1,76 @@ +ActiveAdmin.register_page "SchoolUserUploads" do + + menu :label => 'School User Upload', :parent => 'Misc' + + page_action :upload_schooluseruploads, :method => :post do + User.transaction do + + puts params + + file = params[:jam_ruby_user][:csv] + + + created = 0 + already_existing = 0 + array_of_arrays = CSV.read(file.tempfile.path, headers:true, encoding: 'bom|utf-8') + array_of_arrays.each do |row| + school_name = row['School Name'] + school_tag = row['School ID'] + school = School.autocreate_find_from_upload(school_name, school_tag) + first_name = row['First Name'] + last_name = row['Last Name'] + email_address = row['Email Address'] + license_start = parse_date(row['License Start Date']) + license_end = parse_date(row['License End Date']) + source = row['Source'] + password = SecureRandom.uuid + options = { + first_name: first_name, + last_name: last_name, + email: email_address, + license_start: license_start, + license_end: license_end, + import_source: source, + school_id: school.id, + terms_of_service: true, + musician: true, + skip_recaptcha: true, + password: password, + password_confirmation: password + } + + parse_user_type(row['User Type'], options) + + instrument = Instrument.find('electric guitar') + instruments= [{instrument_id: instrument.id, proficiency_level: 3, priority: 1}] + options[:instruments] = instruments + user = User.signup(options) + + if user.errors.any? + puts "User #{user.name} #{user.email} had errors" + puts user.errors.inspect + already_existing = already_existing + 1 + else + puts "User #{user.email} created" + created = created + 1 + end + end + + redirect_to admin_schooluseruploads_path, :notice => "Created #{created} school students. Ignored #{already_existing} because already existed." + end + end + + content do + panel "Help" do + link_to "Download Sample CSV", asset_path("Sample_School_User_Upload.csv", target: "_blank", download: "Sample_School_User_Upload.csv") + end + + active_admin_form_for User.new, :url => admin_schooluseruploads_upload_schooluseruploads_path, :builder => ActiveAdmin::FormBuilder do |f| + f.inputs "Upload School Users" do + f.input :csv, as: :file, required: true, :label => "A school user upload" + end + f.actions + end + end +end + diff --git a/admin/app/assets/csvs/Sample_School_User_Upload.csv b/admin/app/assets/csvs/Sample_School_User_Upload.csv new file mode 100644 index 000000000..be9022424 --- /dev/null +++ b/admin/app/assets/csvs/Sample_School_User_Upload.csv @@ -0,0 +1 @@ +First Name,Last Name,Email Address,User Type,School ID,School Name,License Start Date,License End Date,Source Student,Student,seth+student1@jamkazam.com,Student,school_a,School A,1/1/20,1/1/21,K12 Student,Expired,seth+student2@jamkazam.com,Student,school_a,School A,1/2/19,1/1/20,K12 Teacher,Teacher,seth+teacher1@jamkazam.com,Student Instructor,school_a,School A,1/1/20,1/1/21,K12 Platform,Instructor,seth+platform1@jamkazam.com,Platform Instructor,school_a,School A,1/1/20,1/2/21,K12 \ No newline at end of file diff --git a/admin/app/controllers/arses_controller.rb b/admin/app/controllers/arses_controller.rb index 9e1559d35..82d73c2f1 100644 --- a/admin/app/controllers/arses_controller.rb +++ b/admin/app/controllers/arses_controller.rb @@ -10,8 +10,13 @@ class ArsesController < ApplicationController ip = params[:ip] username = params[:username] password = params[:password] + topology = params[:topology] + ars_id = params[:ars_id] + puts "TOPOLOGY #{topology}" - ars = Ars.find_by_name(name) + if ars_id + ars = Ars.find_by_id_int(ars_id) + end if ars.nil? ars = Ars.new ars.name = name @@ -22,6 +27,14 @@ class ArsesController < ApplicationController ars.ip = ip ars.password = password ars.username = username + if topology + ars.city = topology['city'] + ars.country = topology['country'] + ars.continent = topology['continent'] + ars.latitude = topology['latitude'] + ars.longitude = topology['longitude'] + ars.subdivision = topology['subdivision'] + end ars.save @ars = ars diff --git a/admin/app/helpers/application_helper.rb b/admin/app/helpers/application_helper.rb index 6e9385e59..c1545e10f 100644 --- a/admin/app/helpers/application_helper.rb +++ b/admin/app/helpers/application_helper.rb @@ -1,4 +1,43 @@ module ApplicationHelper + def parse_user_type(user_type, options) + if user_type == 'Student' + options[:student] = true + elsif user_type == 'Student Instructor' + options[:teacher] = true + elsif user_type == 'Platform Instructor' + options[:platform_instructor] = true + else + raise JamRuby::JamPermissionError, "Unknown user type #{user_type}" + end + end + + def parse_date(date) + delimiter = '/' + bits = date.split(delimiter) + + if bits.length != 3 + delimiter = '-' + bits = date.split(delimiter) + end + + if bits.length != 3 + raise JamRuby::JamPermissionError, "date #{date} has no '-' or '/'" + end + + if bits[2].length == 4 || (bits[0].length != 4 && bits[2].to_i > 12) # excel likes to do 1/1/20. So if last + if bits[2].length == 2 + # prepend year + + date = [bits[0], bits[1], '20' + bits[2]].join(delimiter) + end + Date.strptime(date, "%m#{delimiter}%d#{delimiter}%Y") + else + Date.strptime(date, "%Y#{delimiter}%m#{delimiter}%d") + end + + end + + end diff --git a/admin/app/views/admin/users/_form.html.slim b/admin/app/views/admin/users/_form.html.slim index df29c3115..adae73563 100644 --- a/admin/app/views/admin/users/_form.html.slim +++ b/admin/app/views/admin/users/_form.html.slim @@ -4,6 +4,7 @@ = f.input :admin = f.input :is_onboarder, label: 'Is Support Consultant' = f.input :subscribe_email, label: 'Subscribed to Emails?' + = f.input :is_platform_instructor, label: 'Is Platform Instructor?' = f.input :gifted_jamtracks, label: 'JamTrack Credits' = f.input :first_name = f.input :last_name diff --git a/admin/bin/start b/admin/bin/start new file mode 100755 index 000000000..39d09d1be --- /dev/null +++ b/admin/bin/start @@ -0,0 +1,3 @@ +#!/bin/bash + +bundle exec rails s -b 127.0.0.1 diff --git a/admin/config/application.rb b/admin/config/application.rb index 9e89690ac..cffb75506 100644 --- a/admin/config/application.rb +++ b/admin/config/application.rb @@ -37,6 +37,7 @@ module JamAdmin # Activate observers that should always be running. config.active_record.observers = "JamRuby::InvitedUserObserver" + config.assets.paths << "#{Rails.root}/app/assets/csvs" config.assets.prefix = "#{ENV['RAILS_RELATIVE_URL_ROOT']}/assets" # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. @@ -116,14 +117,16 @@ module JamAdmin config.email_social_alias = 'social@jamkazam.com' config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails config.email_generic_from = 'nobody@jamkazam.com' - config.email_smtp_address = 'smtp.sendgrid.net' + config.email_smtp_address = 'email-smtp.us-east-1.amazonaws.com' config.email_smtp_port = 587 config.email_smtp_domain = 'www.jamkazam.com' config.email_smtp_authentication = :plain - config.email_smtp_user_name = 'jamkazam' - config.email_smtp_password = 'snorkeltoesniffyfarce1' + config.email_smtp_user_name = 'AKIA2SXEHOQFKRW3OWMG' # ses-smtp-user.20200526-212148 + config.email_smtp_password = 'BJZEdTkTcuIrN1koG40PQ2JLHdMmTprC/aLj48Q5KhWJ' config.email_smtp_starttls_auto = true + config.verify_email_enabled = false + config.musician_count = '200,000+' config.facebook_app_id = ENV['FACEBOOK_APP_ID'] || '468555793186398' config.facebook_app_secret = ENV['FACEBOOK_APP_SECRET'] || '546a5b253972f3e2e8b36d9a3dd5a06e' diff --git a/admin/config/initializers/jam_ruby_ars.rb b/admin/config/initializers/jam_ruby_ars.rb new file mode 100644 index 000000000..2fe51d24c --- /dev/null +++ b/admin/config/initializers/jam_ruby_ars.rb @@ -0,0 +1,5 @@ +class JamRuby::Ars + + attr_accessible :password, :username, :active, :beta, :name, :provider, :id_int, :ip, :port, :continent, :country, :city, :subdivision, :latitude, :longitude, as: :admin + +end diff --git a/admin/config/initializers/jam_ruby_user.rb b/admin/config/initializers/jam_ruby_user.rb index 8b27e88a8..b6e0ca6e5 100644 --- a/admin/config/initializers/jam_ruby_user.rb +++ b/admin/config/initializers/jam_ruby_user.rb @@ -1,6 +1,6 @@ class JamRuby::User - attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template # :invite_email + attr_accessible :admin, :raw_password, :musician, :can_invite, :photo_url, :session_settings, :confirm_url, :teacher_attributes, :email_template, :is_platform_instructor # :invite_email accepts_nested_attributes_for :teacher, allow_destroy: true diff --git a/db/up/find_sessions_2020.sql b/db/up/find_sessions_2020.sql index f95fe61b2..895f03624 100644 --- a/db/up/find_sessions_2020.sql +++ b/db/up/find_sessions_2020.sql @@ -58,11 +58,44 @@ ALTER TABLE arses ADD COLUMN beta BOOLEAN default FALSE; ALTER TABLE generic_state ADD COLUMN event_page_top_logo_url VARCHAR(100000) DEFAULT '/assets/event/eventbrite-logo.png'; +ALTER TABLE schools ADD CONSTRAINT schools_name_uniqkey UNIQUE (name); +ALTER TABLE schools ADD COLUMN school_tag VARCHAR(100) UNIQUE; +ALTER TABLE active_music_sessions ADD COLUMN school_id INT; +ALTER TABLE active_music_sessions ADD COLUMN is_platform_instructor BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE active_music_sessions ADD CONSTRAINT active_music_sessions_school_id_fkey FOREIGN KEY (school_id) REFERENCES schools(id); +ALTER TABLE music_sessions ADD COLUMN school_id INT; +ALTER TABLE music_sessions ADD CONSTRAINT music_sessions_school_id_fkey FOREIGN KEY (school_id) REFERENCES schools(id); +ALTER TABLE music_sessions ADD COLUMN is_platform_instructor BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE recordings ADD COLUMN school_id INT; +ALTER TABLE recordings ADD COLUMN is_platform_instructor BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE feeds ADD COLUMN school_id INT; +ALTER TABLE feeds ADD COLUMN is_platform_instructor BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE users ADD COLUMN is_platform_instructor BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE users ADD COLUMN import_source varchar(50); +ALTER TABLE users ADD COLUMN license_start date; +ALTER TABLE users ADD COLUMN license_end date; + + +CREATE INDEX users_is_a_student_idx ON users((1)) WHERE is_a_student; +CREATE INDEX users_is_a_teacher_idx ON users((1)) WHERE is_a_teacher; +CREATE INDEX users_is_platform_instructor_idx ON users((1)) WHERE is_platform_instructor; +CREATE INDEX ams_is_platform_instructor_idx ON active_music_sessions((1)) WHERE is_platform_instructor; +CREATE INDEX sms_is_platform_instructor_idx ON music_sessions((1)) WHERE is_platform_instructor; +CREATE INDEX users_schood_id_idx ON users USING btree (school_id); +CREATE INDEX feeds_schood_id_idx ON feeds USING btree (school_id); +CREATE INDEX feeds_is_platform_instructor_idx ON feeds((1)) WHERE is_platform_instructor; + +ALTER TABLE arses ADD COLUMN country VARCHAR(200); +ALTER TABLE arses ADD COLUMN city VARCHAR(200); +ALTER TABLE arses ADD COLUMN latitude NUMERIC(15,10); +ALTER TABLE arses ADD COLUMN longitude NUMERIC(15,10); +ALTER TABLE arses ADD COLUMN subdivision VARCHAR(200); +ALTER TABLE arses ADD COLUMN continent VARCHAR(200); + + ALTER TABLE users ADD COLUMN recurly_subscription_id VARCHAR(100) DEFAULT NULL; ALTER TABLE users ADD COLUMN recurly_token VARCHAR(200) DEFAULT NULL; ALTER TABLE users ADD COLUMN recurly_subscription_state VARCHAR(20) DEFAULT NULL; - - CREATE TABLE subscriptions ( id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(200) UNIQUE NOT NULL UNIQUE NOT NULL, @@ -79,4 +112,4 @@ CREATE TABLE subscriptions ( max_players_per_session INT DEFAULT 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/pb/src/client_container.proto b/pb/src/client_container.proto index db747dac8..0eb19091a 100644 --- a/pb/src/client_container.proto +++ b/pb/src/client_container.proto @@ -816,6 +816,12 @@ message Ars { optional string username = 4; optional string password = 5; optional int32 port = 6; + optional string country = 7; + optional string continent = 8; + optional string subdivision = 9; + optional double latitude = 10; + optional double longitude = 11; + optional string city = 12; } // target: client diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index daa048f00..1d23e2a63 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -35,8 +35,9 @@ module JamRuby end end - def welcome_message(user) + def welcome_message(user, reset_url = nil) @user = user + @reset_url = reset_url sendgrid_category "Welcome" sendgrid_unique_args :type => "welcome_message" @@ -218,6 +219,25 @@ module JamRuby end end + def school_welcome_message(user, reset_url) + @user = user + @subject= "Set a password on your new JamKazam account for your #{user.school.name} music program" + @school = user.school + @reset_url = reset_url + + sendgrid_category "Welcome" + sendgrid_unique_args :type => "welcome_message" + + sendgrid_recipients([user.email]) + sendgrid_substitute('@USERID', [user.id]) + sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name]) + + mail(:to => user.email, :subject => @subject) do |format| + format.text + format.html + end + end + def teacher_welcome_message(user) @user = user @subject= "Welcome to JamKazam and JamClass online lessons!" diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.html.erb new file mode 100644 index 000000000..db1bf29cf --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.html.erb @@ -0,0 +1,46 @@ +<% provide(:title, @subject) %> + + +<% if !@user.anonymous? %> +

Hello <%= @vars[EmailBatch::VAR_FIRST_NAME] %> -- +

+<% end %> + +

+ Your school <%= @school.name %> has set up a JamKazam account for you, + so that you can participate in an online music education program through your school. + JamKazam is an application and a platform that lets you play music with other students over the Internet, live and in sync. + You can also use JamKazam to play and record yourself on your own. +

+ +

+ To use the JamKazam app, you will need to sign in to the app using an email address and a password. + The email address is the one to which this email was sent. + Click the button below to set a password for your JamKazam account. + If you're worried this is a scam, please check with your school or music program instructor to verify that this is a legitimate email. +

+ +
+

+ + Set Password + +

+
+ +

+ Your instructor will help you to start using the JamKazam app in your music program with other students. + If you already have your gear and want to set it up and start playing around with it, + you can check out our summary setup instructions + https://jamkazam.freshdesk.com/support/solutions/articles/66000259828 + and also learn about the features you can use to create, join, and play in online music sessions + https://jamkazam.freshdesk.com/support/solutions/66000073845. +

+

+ We hope you enjoy playing music on the JamKazam platform! If you run into trouble, please use this page to ask for help + https://jamkazam.freshdesk.com/support/tickets/new. +

+ + +

Best Regards,
+ Team JamKazam

\ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.text.erb new file mode 100644 index 000000000..306724c13 --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_welcome_message.text.erb @@ -0,0 +1,28 @@ +<% if !@user.anonymous? %> +Hello <%= @vars[EmailBatch::VAR_FIRST_NAME] %> -- +<% end %> + +Your school <%= @school.name %> has set up a JamKazam account for you, +so that you can participate in an online music education program through your school. +JamKazam is an application and a platform that lets you play music with other students over the Internet, live and in sync. +You can also use JamKazam to play and record yourself on your own. + +To use the JamKazam app, you will need to sign in to the app using an email address and a password. +The email address is the one to which this email was sent. +Click the button below to set a password for your JamKazam account. +If you're worried this is a scam, please check with your school or music program instructor to verify that this is a legitimate email. + +Set Password: <%= @reset_url %> + +Your instructor will help you to start using the JamKazam app in your music program with other students. +If you already have your gear and want to set it up and start playing around with it, +you can check out our summary setup instructions https://jamkazam.freshdesk.com/support/solutions/articles/66000259828 +and also learn about the features you can use to create, join, and play in online music sessions + +https://jamkazam.freshdesk.com/support/solutions/66000073845. + +We hope you enjoy playing music on the JamKazam platform! If you run into trouble, please use this page to ask for help +https://jamkazam.freshdesk.com/support/tickets/new. + +Best Regards, +Team JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb index d1cb98bc4..62c05046c 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/welcome_message.html.erb @@ -12,6 +12,20 @@ your inbox so you can refer back to the links if needed.

+<% if @reset_url %> +

+ Your account was imported for you, so you'll need to set a password. + Click the button below to set a password for your JamKazam account. +

+
+

+ + Set Password + +

+
+ <% end %> +

For Playing Music Together Live & In Sync From Different Locations
JamKazam's Mac and Windows desktop apps let musicians play together live and in sync with high-quality audio from different locations over the Internet, with an amazing feature set for diff --git a/ruby/lib/jam_ruby/connection_manager.rb b/ruby/lib/jam_ruby/connection_manager.rb index 02b1d0845..384110fa6 100644 --- a/ruby/lib/jam_ruby/connection_manager.rb +++ b/ruby/lib/jam_ruby/connection_manager.rb @@ -353,19 +353,22 @@ SQL end def update_session_controller(music_session_id) + tracks_changed = false active_music_session = ActiveMusicSession.find(music_session_id) if active_music_session music_session = active_music_session.music_session if music_session.session_controller_id && !active_music_session.users.exists?(music_session.session_controller.id) # find next in line, because the current 'session controller' is not part of the session - next_in_line(music_session, active_music_session) + tracks_changed = next_in_line(music_session, active_music_session) end end + tracks_changed end # determine who should be session controller after someone leaves def next_in_line(music_session, active_music_session) + tracks_changed = false session_users = active_music_session.users # check friends 1st @@ -374,7 +377,7 @@ SQL music_session.session_controller = session_friends[0] if music_session.save active_music_session.tick_track_changes - Notification.send_tracks_changed(active_music_session) + tracks_changed = true return end end @@ -385,7 +388,7 @@ SQL music_session.session_controller = invited[0] if music_session.save active_music_session.tick_track_changes - Notification.send_tracks_changed(active_music_session) + tracks_changed = true return end end @@ -397,16 +400,17 @@ SQL music_session.session_controller = earliest if music_session.save active_music_session.tick_track_changes - Notification.send_tracks_changed(active_music_session) + tracks_changed = true return end end - music_session.creator + tracks_changed end def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency, client_role = nil, parent_client_id = nil, video_sources=nil) connection = nil + tracks_changed = false ConnectionManager.active_record_transaction do |connection_manager| db_conn = connection_manager.pg_conn @@ -432,11 +436,15 @@ SQL if connection.errors.any? raise ActiveRecord::Rollback else - update_session_controller(music_session.id) + tracks_changed = update_session_controller(music_session.id) end end + if tracks_changed + Notification.send_tracks_changed(music_session.active_music_session) + end + connection end @@ -444,6 +452,7 @@ SQL # if a blk is passed in, upon success, it will be called and you can issue notifications # within the connection table lock def leave_music_session(user, connection, music_session, &blk) + send_tracks_changed = false ConnectionManager.active_record_transaction do |connection_manager| conn = connection_manager.pg_conn @@ -469,7 +478,7 @@ SQL if result.cmd_tuples == 1 @log.debug("disassociated music_session with connection for client_id=#{client_id}, user_id=#{user_id}") - update_session_controller(music_session.id) + send_tracks_changed = update_session_controller(music_session.id) JamRuby::MusicSessionUserHistory.removed_music_session(user_id, music_session_id) session_checks(conn, previous_music_session_id, user_id) @@ -484,6 +493,10 @@ SQL end end end + + if send_tracks_changed + Notification.send_tracks_changed(music_session.active_music_session) + end end def lock_connections(conn) diff --git a/ruby/lib/jam_ruby/constants/validation_messages.rb b/ruby/lib/jam_ruby/constants/validation_messages.rb index da90d06cd..7dbaf3bb4 100644 --- a/ruby/lib/jam_ruby/constants/validation_messages.rb +++ b/ruby/lib/jam_ruby/constants/validation_messages.rb @@ -62,6 +62,17 @@ module ValidationMessages FANS_CAN_NOT_JOIN = "Fans can not join this session" CANT_JOIN_RECORDING_SESSION = "is currently recording" CANT_JOIN_MULTIPLE_SESSIONS = 'You cannot join more than one music session' + CANT_JOIN_SCHOOL_SESSION = "You can not join school sessions" + CAN_ONLY_JOIN_SAME_SCHOOL_SESSION = "You can only join sessions from your school" + LICENSE_EXPIRED = "Your license has expired" + LICENSE_NOT_STARTED = "Your license has not started" + + # chat + CAN_ONLY_CHAT_SAME_SCHOOL = "You can only message others from your school" + DISABLED_GLOBAL_SCHOOL_CHAT = "Global chat disabled for schools" + + # permissions + CAN_ONLY_VIEW_SAME_SCHOOL = "You can only view other users from your school" # recordings ALREADY_BEING_RECORDED = "already being recorded" diff --git a/ruby/lib/jam_ruby/message_factory.rb b/ruby/lib/jam_ruby/message_factory.rb index 687a0fba1..f4d9844ec 100644 --- a/ruby/lib/jam_ruby/message_factory.rb +++ b/ruby/lib/jam_ruby/message_factory.rb @@ -68,8 +68,23 @@ module JamRuby ) end + def ars_body(ars) + Jampb::Ars.new( + :id => ars.id_int, + :ip => ars.ip, + :username => ars.username, + :password => ars.password, + :port => ars.port, + :country => ars.country, + :continent => ars.continent, + :city => ars.city, + :subdivision => ars.subdivision, + :latitude => ars.latitude, + :longitude => ars.longitude + ) + end # create a login ack (login was successful) - def login_ack(public_ip, client_id, token, heartbeat_interval, music_session_id, reconnected, user_id, connection_expire_time, username, client_id_int, client_update_data = nil, ars_list = nil) + def login_ack(public_ip, client_id, token, heartbeat_interval, music_session_id, reconnected, user_id, connection_expire_time, username, client_id_int, client_update_data = nil, arses = []) client_update = Jampb::ClientUpdate.new( product: client_update_data[:product], version: client_update_data[:version], @@ -77,18 +92,6 @@ module JamRuby size: client_update_data[:size] ) if client_update_data - arses = [] - - ars_list.each do |ars| - arses << Jampb::Ars.new( - :id => ars.id_int, - :ip => ars.ip, - :username => ars.username, - :password => ars.password, - :port => ars.port - ) - end if ars_list - login_ack = Jampb::LoginAck.new( :public_ip => public_ip, diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index 32545b48b..489cc3e8a 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -199,6 +199,8 @@ module JamRuby } ) + query = Search.scope_schools_together_sessions(query, user) + if as_musician query = query.where( %Q{ @@ -302,7 +304,7 @@ module JamRuby end # all sessions that are private and active, yet I can see - def self.public_index(user, options) + def self.public_index(user, options) session_id = options[:session_id] genre = options[:genre] @@ -317,6 +319,7 @@ module JamRuby query = query.where("musician_access = TRUE") + query = Search.scope_schools_together_sessions(query, user) # if not specified, default offset to 0 offset ||= 0 @@ -416,6 +419,8 @@ module JamRuby } ) + query = Search.scope_schools_together_sessions(query, user) + query = query.offset(offset) if offset query = query.limit(limit) if limit @@ -607,6 +612,7 @@ module JamRuby active_music_session.with_lock do # VRFS-1297 active_music_session.tick_track_changes + Notification.send_tracks_changed(active_music_session) # VRFS-3986 connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, client_role, parent_client_id, video_sources) @@ -654,6 +660,8 @@ module JamRuby active_music_session = ActiveMusicSession.new active_music_session.id = music_session.id # copy the .id from music_session to active_music_session active_music_session.creator = user + active_music_session.school_id = user.school_id + active_music_session.is_platform_instructor = user.is_platform_instructor if music_session.fan_access # create an icecast mount since regular users can listen in to the broadcast @@ -873,6 +881,8 @@ module JamRuby feed.music_session_id = self.id end + feed.school_id = self.school_id + feed.is_platform_instructor = self.is_platform_instructor feed.active = true feed.save diff --git a/ruby/lib/jam_ruby/models/chat_message.rb b/ruby/lib/jam_ruby/models/chat_message.rb index 478962532..07baa73f0 100644 --- a/ruby/lib/jam_ruby/models/chat_message.rb +++ b/ruby/lib/jam_ruby/models/chat_message.rb @@ -24,6 +24,25 @@ module JamRuby validates :user, presence: true validates :message, length: {minimum: 1, maximum: 255}, no_profanity: true, unless: :ignore_message_checks + validate :same_school_protection + validate :no_global_for_schools + + def no_global_for_schools + if self.channel == 'global' && user && !user.school_id.nil? + errors.add(:user, ValidationMessages::DISABLED_GLOBAL_SCHOOL_CHAT) + end + end + + def same_school_protection + if user && target_user + if !user.is_platform_instructor && !target_user.is_platform_instructor + if user.school_id != target_user.school_id + errors.add(:target_user, ValidationMessages::CAN_ONLY_CHAT_SAME_SCHOOL) + end + end + end + end + def self.create(user, music_session, message, channel, client_id, target_user = nil, lesson_session = nil, purpose = nil, music_notation = nil, recording = nil) source_user = user @@ -88,6 +107,11 @@ module JamRuby @@message_factory = MessageFactory.new def index(user, params = {}) + # TODO: school user scan't see chat + if params[:channel] == 'global' && !user.school_id.nil? + return [[], nil] + end + limit = params[:limit] limit ||= 20 limit = limit.to_i diff --git a/ruby/lib/jam_ruby/models/connection.rb b/ruby/lib/jam_ruby/models/connection.rb index d8136a486..3481e99b1 100644 --- a/ruby/lib/jam_ruby/models/connection.rb +++ b/ruby/lib/jam_ruby/models/connection.rb @@ -108,6 +108,7 @@ module JamRuby return false end + if as_musician unless self.user.musician errors.add(:as_musician, ValidationMessages::FAN_CAN_NOT_JOIN_AS_MUSICIAN) @@ -148,6 +149,23 @@ module JamRuby errors.add(:music_session, ValidationMessages::CANT_JOIN_RECORDING_SESSION) end + # same logic as Search.scope_schools_together_sessions + if !self.user.is_platform_instructor + if self.user.school_id.nil? && !music_session.school_id.nil? + errors.add(:music_session, ValidationMessages::CANT_JOIN_SCHOOL_SESSION) + elsif !self.user.school_id.nil? && (self.user.school_id != music_session.school_id) + errors.add(:music_session, ValidationMessages::CAN_ONLY_JOIN_SAME_SCHOOL_SESSION) + end + end + + if self.user.license_expired? + errors.add(:music_session, ValidationMessages::LICENSE_EXPIRED) + end + + if self.user.license_not_started? + errors.add(:music_session, ValidationMessages::LICENSE_NOT_STARTED) + end + # unless user.admin? # num_sessions = Connection.where(:user_id => user_id) # .where(["(music_session_id IS NOT NULL) AND (aasm_state != ?)",EXPIRED_STATE.to_s]) diff --git a/ruby/lib/jam_ruby/models/feed.rb b/ruby/lib/jam_ruby/models/feed.rb index 89d522aae..befdc900a 100644 --- a/ruby/lib/jam_ruby/models/feed.rb +++ b/ruby/lib/jam_ruby/models/feed.rb @@ -37,6 +37,8 @@ module JamRuby .limit(limit) .where('feeds.recording_id is NULL OR (recordings.all_discarded = false AND recordings.deleted = false)') # remove any 'all_discarded recordings from the search results' or 'deleted' + query = Search.scope_schools_together_feeds(query, user) + # handle sort if sort == 'date' query = query.order('feeds.id DESC') diff --git a/ruby/lib/jam_ruby/models/friend_request.rb b/ruby/lib/jam_ruby/models/friend_request.rb index 3b6d930a7..f6b57a42b 100644 --- a/ruby/lib/jam_ruby/models/friend_request.rb +++ b/ruby/lib/jam_ruby/models/friend_request.rb @@ -15,6 +15,25 @@ module JamRuby #validates :status, :inclusion => {:in => STATUS} validates :message, no_profanity: true + validate :same_school_protection + + def same_school_protection + if self.user_id && self.user.nil? + self.user = User.find(user_id) + end + if self.friend_id && self.friend.nil? + self.friend = User.find(friend_id) + end + + if self.user && self.friend + if !self.user.is_platform_instructor && !self.friend.is_platform_instructor + if self.user.school_id != self.friend.school_id + errors.add(:friend, ValidationMessages::CAN_ONLY_CHAT_SAME_SCHOOL) + end + end + end + end + def to_s "#{self.id} => #{self.user.to_s}:#{self.friend.to_s}" end @@ -32,10 +51,11 @@ module JamRuby friend_request.user_id = user_id friend_request.friend_id = friend_id friend_request.message = message - friend_request.save + if friend_request.save + # send notification + Notification.send_friend_request(friend_request.id, user_id, friend_id) unless supress_initial + end - # send notification - Notification.send_friend_request(friend_request.id, user_id, friend_id) unless supress_initial else ActiveRecord::Base.transaction do @@ -52,10 +72,10 @@ module JamRuby # create both records for this friendship if friend_request.status == "accept" - Friendship.save(friend_request.user_id, friend_request.friend_id) - - # send notification - Notification.send_friend_request_accepted(friend_request.user_id, friend_request.friend_id) + if Friendship.save(friend_request.user_id, friend_request.friend_id) + # send notification + Notification.send_friend_request_accepted(friend_request.user_id, friend_request.friend_id) + end end end end diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index d3744553c..96f8ca7a5 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -346,6 +346,8 @@ module JamRuby new_session.is_unstructured_rsvp = self.is_unstructured_rsvp new_session.legal_terms = true new_session.session_controller = self.session_controller + new_session.school_id = self.school_id + new_session.is_platform_instructor = self.is_platform_instructor # copy rsvp_slots, rsvp_requests, and rsvp_requests_rsvp_slots RsvpSlot.where("music_session_id = '#{self.id}'").find_each do |slot| @@ -602,6 +604,8 @@ module JamRuby #query = query.where("music_sessions.user_id = '#{user.id}' OR invitations.id IS NOT NULL") query = query.where("(rsvp_requests.id IS NOT NULL AND rsvp_requests_rsvp_slots.id IS NOT NULL AND rsvp_requests.user_id = '#{user.id}' AND rsvp_requests_rsvp_slots.chosen = true) OR (invitations.id IS NOT NULL) OR (music_sessions.user_id = '#{user.id}') ") + query = Search.scope_schools_together_sessions(query, user, 'music_sessions') + query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished} OR #{session_started_not_finished}") query = query.where("music_sessions.create_type IS NULL OR (music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}' AND music_sessions.create_type != '#{CREATE_TYPE_QUICK_PUBLIC}')") query = query.order("music_sessions.scheduled_start ASC") @@ -630,6 +634,8 @@ module JamRuby } ) + query = Search.scope_schools_together_sessions(query, user, 'music_sessions') + query = query.where(%Q{music_sessions.old = FALSE AND music_sessions.canceled = FALSE AND (music_sessions.create_type is NULL OR (music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}' AND music_sessions.create_type != '#{CREATE_TYPE_QUICK_PUBLIC}')) AND (music_sessions.scheduled_start is NULL OR music_sessions.scheduled_start > NOW() - '4 hour'::INTERVAL) AND rsvp_requests.user_id = '#{user.id}' #{filter_approved}} @@ -663,6 +669,8 @@ module JamRuby ms.is_unstructured_rsvp = options[:isUnstructuredRsvp] if options[:isUnstructuredRsvp] ms.scheduled_start = parse_scheduled_start(options[:start], options[:timezone]) if options[:start] && options[:timezone] ms.scheduled_start = options[:scheduled_start] if options[:scheduled_start] + ms.school_id = user.school_id + ms.is_platform_instructor = user.is_platform_instructor if options[:lesson_session] ms.lesson_session = options[:lesson_session] end @@ -1167,6 +1175,7 @@ SQL # keep only rsvp/invitation/friend results. Nice tailored active list now! query = query.where("open_rsvps = TRUE OR rsvp_requests.id IS NOT NULL OR invitations.id IS NOT NULL or music_sessions.user_id = '#{user.id}' OR (friendships.id IS NOT NULL AND friendships_2.id IS NOT NULL)") + query = Search.scope_schools_together_sessions(query, user, 'music_sessions') # if not specified, default offset to 0 offset ||= 0 diff --git a/ruby/lib/jam_ruby/models/musician_search.rb b/ruby/lib/jam_ruby/models/musician_search.rb index f11e36e20..1071f95a5 100644 --- a/ruby/lib/jam_ruby/models/musician_search.rb +++ b/ruby/lib/jam_ruby/models/musician_search.rb @@ -145,6 +145,7 @@ module JamRuby def do_search(params={}) rel = User.musicians.where('users.id <> ?', self.user.id) + rel = Search.scope_schools_together(rel, self.user) rel = self._genres(rel) rel = self._ages(rel) rel = self._studios(rel) diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index e0bb97fff..182d6ddb9 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -20,6 +20,16 @@ module JamRuby validates :target_user, :presence => true validates :message, length: {minimum: 1, maximum: 400}, no_profanity: true, if: :text_message? validate :different_source_target, if: :text_message? + validate :same_school_protection + def same_school_protection + if source_user && target_user + if !source_user.is_platform_instructor && !target_user.is_platform_instructor + if source_user.school_id != target_user.school_id + errors.add(:target_user, ValidationMessages::CAN_ONLY_CHAT_SAME_SCHOOL) + end + end + end + end def different_source_target unless target_user_id.nil? || source_user_id.nil? diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index 23e92e063..926144983 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -44,6 +44,8 @@ module JamRuby def add_to_feed feed = Feed.new feed.recording = self + feed.is_platform_instructor = self.is_platform_instructor + feed.school_id = self.school_id end def sanitize_active_admin @@ -226,6 +228,8 @@ module JamRuby recording = Recording.new recording.music_session = nil recording.owner = owner + recording.school_id = owner.school_id + recording.is_platform_instructor = owner.is_platform_instructor recording.band = nil recording.immediate = true # immediate in practice means 'the ios app uploaded this' recording.video = params[:record_video] @@ -268,6 +272,8 @@ module JamRuby recording.music_session = music_session recording.owner = owner recording.band = music_session.band + recording.school_id = owner.school_id + recording.is_platform_instructor = owner.is_platform_instructor recording.video = record_video == true || record_video == 'true' if recording.save diff --git a/ruby/lib/jam_ruby/models/school.rb b/ruby/lib/jam_ruby/models/school.rb index 6a9f32bbd..86b5b9e2c 100644 --- a/ruby/lib/jam_ruby/models/school.rb +++ b/ruby/lib/jam_ruby/models/school.rb @@ -33,6 +33,22 @@ module JamRuby after_create :create_affiliate #before_save :stringify_avatar_info, :if => :updating_avatar + def self.autocreate_find_from_upload(school_name, school_tag) + if school_name.blank? + return nil + end + + school = School.find_by_name(school_name) + if school.nil? + school = School.new + school.name = school_name + school.user = User.find_by_email('seth@jamkazam.com') + school.school_tag = school_tag + school.education = true + school.save! + end + school + end def is_education? education end diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb index 0fa2e28b8..132addef4 100644 --- a/ruby/lib/jam_ruby/models/search.rb +++ b/ruby/lib/jam_ruby/models/search.rb @@ -84,7 +84,8 @@ module JamRuby User.musicians end @results = rel.where("(name_tsv @@ to_tsquery('jamenglish', ?))", tsquery).limit(10) - @results + + @results = Search.scope_schools_together(@results, user) end class << self @@ -114,6 +115,73 @@ module JamRuby srch end + def scope_schools_together_feeds(rel, user) + if user.nil? + return rel.where("feeds.school_id is null") + end + + # platform instructors can search anybody (non-school and school). So no nothing special for them. + + if !user.is_platform_instructor + # for everyone else... + # make sure you can only see same-school. Or in the case of 'null school', you'll get other non-schoolers (i.e. normies) + # also, make sure anyone will find platform_instructors + if user.school_id.nil? + rel = rel.where("feeds.school_id is null") + else + rel = rel.where("feeds.school_id = #{user.school_id} OR feeds.is_platform_instructor") + end + end + + rel + end + + def scope_schools_together_chats(rel, user) + # TODO: + return rel + end + + + def scope_schools_together_sessions(rel, user, table_name = 'active_music_sessions') + if user.nil? + return rel.where("#{table_name}.school_id is null") + end + # platform instructors can search anybody (non-school and school). So no nothing special for them. + + if !user.is_platform_instructor + # for everyone else... + # make sure you can only see same-school. Or in the case of 'null school', you'll get other non-schoolers (i.e. normies) + # also, make sure anyone will find platform_instructors + if user.school_id.nil? + rel = rel.where("#{table_name}.school_id is null") + else + rel = rel.where("#{table_name}.school_id = #{user.school_id} OR #{table_name}.is_platform_instructor") + end + end + + rel + end + + def scope_schools_together(rel, user) + if user.nil? + return rel.where("school_id is null") + end + # platform instructors can search anybody (non-school and school). So no nothing special for them. + + if !user.is_platform_instructor + # for everyone else... + # make sure you can only see same-school. Or in the case of 'null school', you'll get other non-schoolers (i.e. normies) + # also, make sure anyone will find platform_instructors + if user.school_id.nil? + rel = rel.where("school_id is null") + else + rel = rel.where("school_id = #{user.school_id} OR is_platform_instructor") + end + end + + rel + end + def text_search(params, user = nil) srch = Search.new unless (params.blank? || params[:query].blank? || 2 > params[:query].length) @@ -171,6 +239,8 @@ module JamRuby .where(['minst.instrument_id = ?', instrument]) end + rel = scope_schools_together(rel, user) + # to find appropriate musicians we need to join users with scores to get to those with no scores or bad scores # weeded out diff --git a/ruby/lib/jam_ruby/models/text_message.rb b/ruby/lib/jam_ruby/models/text_message.rb index ca6d8b7bc..549182751 100644 --- a/ruby/lib/jam_ruby/models/text_message.rb +++ b/ruby/lib/jam_ruby/models/text_message.rb @@ -12,6 +12,17 @@ module JamRuby belongs_to :target_user, :class_name => "JamRuby::User", :foreign_key => "target_user_id" belongs_to :source_user, :class_name => "JamRuby::User", :foreign_key => "source_user_id" + validate :same_school_protection + def same_school_protection + if source_user && target_user + if !source_user.is_platform_instructor && !target_user.is_platform_instructor + if source_user.school_id != target_user.school_id + errors.add(:target_user, ValidationMessages::CAN_ONLY_CHAT_SAME_SCHOOL) + end + end + end + end + validates :message, length: {minimum: 1, maximum: 400}, no_profanity: true def self.index(target_user_id, source_user_id, options = {}) diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 99bc0aa4b..f86bf186b 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -718,6 +718,16 @@ module JamRuby self.birth_date.nil? ? nil : now.year - self.birth_date.year - (self.birth_date.to_date.change(:year => now.year) > now ? 1 : 0) end + # has the user's license started? only valid if they have a license + def license_not_started? + license_start && Time.now < license_start + end + + # has the user's license ended? Only valid if they have a license + def license_expired? + license_end && Time.now > license_end + end + def session_count 0 #MusicSession.where("user_id = ? AND started_at IS NOT NULL", self.id).size @@ -957,8 +967,14 @@ module JamRuby if user.reset_password_token != token raise JamRuby::JamArgumentError.new("Invalid reset token", "token") end - if Time.now - user.reset_password_token_created > 3.days - raise JamRuby::JamArgumentError.new("Password reset has expired", "token") + if user.import_source + if Time.now - user.reset_password_token_created > 180.days + raise JamRuby::JamArgumentError.new("Password reset has expired", "token") + end + else + if Time.now - user.reset_password_token_created > 3.days + raise JamRuby::JamArgumentError.new("Password reset has expired", "token") + end end if new_password.nil? || new_password == "" raise JamRuby::JamArgumentError.new("Password is empty", "password") @@ -997,6 +1013,13 @@ module JamRuby user end + def create_tokened_reset_url + self.reset_password_token = SecureRandom.urlsafe_base64 + self.reset_password_token_created = Time.now + self.save + "#{APP_CONFIG.external_root_url}/reset_password_token?token=#{self.reset_password_token}&email=#{CGI.escape(email)}" + end + def self.band_index(user_id) bands = Band.joins(:band_musicians) .where(:bands_musicians => {:user_id => "#{user_id}"}) @@ -1422,6 +1445,10 @@ module JamRuby test_drive_package_details = options[:test_drive_package] under_13 = options[:under_13] timezone = options[:timezone] + platform_instructor = options[:platform_instructor] + license_start = options[:license_start] + license_end = options[:license_end] + import_source = options[:import_source] test_drive_package = TestDrivePackage.find_by_name(test_drive_package_details[:name]) if test_drive_package_details @@ -1429,7 +1456,7 @@ module JamRuby retailer = School.find(retailer_id) if retailer_id user = User.new user.validate_instruments = true - UserManager.active_record_transaction do |user_manager| + User.transaction do if school_invitation_code school_invitation = SchoolInvitation.find_by_invitation_code(school_invitation_code) @@ -1454,7 +1481,12 @@ module JamRuby user.first_name = first_name if first_name.present? user.last_name = last_name if last_name.present? user.email = email - user.subscribe_email = true + user.import_source = import_source + user.email_confirmed = !user.import_source.nil? + user.subscribe_email = import_source.nil? + user.license_start = license_start + user.license_end = license_end + user.is_platform_instructor = !!platform_instructor user.terms_of_service = terms_of_service user.reuse_card unless reuse_card.nil? user.gifted_jamtracks = 0 @@ -1490,6 +1522,7 @@ module JamRuby user.affiliate_referral = school.affiliate_partner elsif user.is_a_teacher school = School.find_by_id(school_id) + user.school_id = school_id user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Empty biography", school_id: school_id) user.affiliate_referral = school.affiliate_partner end @@ -1530,7 +1563,7 @@ module JamRuby # user.country = location[:country] user.birth_date = birth_date - if musician + if musician && location user.last_jam_addr = location[:addr] user.last_jam_locidispid = location[:locidispid] user.last_jam_updated_reason = JAM_REASON_REGISTRATION @@ -1709,7 +1742,12 @@ module JamRuby user.handle_test_drive_package(test_drive_package, test_drive_package_details) if test_drive_package - if user.is_a_student + reset_url = nil + if user.import_source + reset_url = user.create_tokened_reset_url + end + + if import_source.nil? && user.is_a_student #if school && school.education # UserMailer.student_education_welcome_message(user).deliver_now #else @@ -1734,8 +1772,20 @@ module JamRuby #end + elsif user.is_a_student + if user.import_source + UserMailer.school_welcome_message(user, reset_url).deliver_now + else + UserMailer.student_welcome_message(user).deliver_now + end elsif user.is_a_teacher - UserMailer.teacher_welcome_message(user).deliver_now + if user.import_source + UserMailer.school_welcome_message(user, reset_url).deliver_now + else + UserMailer.teacher_welcome_message(user).deliver_now + end + elsif user.is_platform_instructor + UserMailer.welcome_message(user, reset_url).deliver_now elsif user.education_interest UserMailer.education_owner_welcome_message(user).deliver_now elsif user.school_interest diff --git a/web/app/assets/javascripts/react-components/FindSessionRow.js.jsx.coffee b/web/app/assets/javascripts/react-components/FindSessionRow.js.jsx.coffee index fea2b82f2..312ffb2ac 100644 --- a/web/app/assets/javascripts/react-components/FindSessionRow.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/FindSessionRow.js.jsx.coffee @@ -8,8 +8,6 @@ MAX_MINUTES_SHOW_START = 15 @FindSessionRow = React.createClass({ - mixins: [Reflux.listenTo(AppStore, "onAppInit")] - ui: null getInitialState: () -> @@ -354,7 +352,7 @@ MAX_MINUTES_SHOW_START = 15 context.JK.SessionUtils.joinSession(sessionId) joinLinkClicked: (session) -> - context.JK.SessionUtils.ensureValidClient(@app, context.JK.GearUtils, @ensuredCallback.bind(this, session.id)) + context.JK.SessionUtils.ensureValidClient(AppStore.app, context.JK.GearUtils, @ensuredCallback.bind(this, session.id)) rsvpLinkClicked: (session) -> @ui.launchRsvpSubmitDialog(session.id) diff --git a/web/app/assets/stylesheets/client/createSession.scss b/web/app/assets/stylesheets/client/createSession.scss index 9e1a33cfd..4a0fbed0d 100644 --- a/web/app/assets/stylesheets/client/createSession.scss +++ b/web/app/assets/stylesheets/client/createSession.scss @@ -84,7 +84,7 @@ } } .learn-more-sessions-header { - margin-top:40px; + margin-top:25px; } .learn-more-sessions { a { diff --git a/web/app/controllers/api_controller.rb b/web/app/controllers/api_controller.rb index 9b3328527..cef52b25b 100644 --- a/web/app/controllers/api_controller.rb +++ b/web/app/controllers/api_controller.rb @@ -90,6 +90,18 @@ class ApiController < ApplicationController @user = User.find(params[:id]) end + def guard_school_same_scope(user, target) + if !user || !target + return true + end + if !user.is_platform_instructor && !target.is_platform_instructor + return user.school_id == target.school_id + else + return true + end + + end + def optional_auth_user if current_user.nil? @user = nil diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb index 2a52877d5..37bb21c52 100644 --- a/web/app/controllers/api_music_sessions_controller.rb +++ b/web/app/controllers/api_music_sessions_controller.rb @@ -147,6 +147,8 @@ class ApiMusicSessionsController < ApiController history.language = 'eng' history.legal_policy = 'standard' history.creator = current_user + history.school_id = current_user.school_id + history.is_platform_instructor = current_user.is_platform_instructor history.save if history.errors.any? diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index 166561ecc..d3b2fcc6b 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -60,6 +60,10 @@ class ApiUsersController < ApiController end def profile_show + if !guard_school_same_scope(current_user, User.find(params[:id])) + raise JamPermissionError, ValidationMessages::CAN_ONLY_VIEW_SAME_SCHOOL + end + @profile = User.includes([{musician_instruments: :instrument}, {band_musicians: :user}, {genre_players: :genre}, diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index 9d221345c..45bd49a7c 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -64,7 +64,7 @@ if current_user && @user == current_user node :show_jamtrack_guide do |user| !user.first_played_jamtrack_at && user.jam_track_rights.count > 0 end - + node :mods do |user| user.mods_json end diff --git a/web/app/views/clients/_scheduledSession.html.erb b/web/app/views/clients/_scheduledSession.html.erb index 54be5bf29..4cf0b4928 100644 --- a/web/app/views/clients/_scheduledSession.html.erb +++ b/web/app/views/clients/_scheduledSession.html.erb @@ -24,10 +24,10 @@

start a session

-
QUICK START SOLO

Use this button to quick start a private session just for yourself. Good for solo practice and gear testing.

-
QUICK START OPEN

Use this button to quick start an open session that anyone can join to play with you, and that fans can listen to.

-
QUICK START FRIENDS

Use this button to quick start a friends-only session. No invitations necessary for any of your friends. Good for those with select friends they always play with.

-
START OR SCHEDULE

Use this button start a wizard that will let you have more control over your session. Schedule future sessions. Start private sessions. Invite other musicians. And lots more...

learn more
+
QUICK START PRIVATE

Quick start a private session now. Good for solo practice. Or invite specific friends to join you.

+
QUICK START PUBLIC

Quick start an open session that anyone can join. Good for meeting others, spontaneous jams.

+
QUICK START FRIENDS

Quick start a friends-only session. No invitations needed. Good for playing with same folks.

+
SCHEDULE FUTURE

Use a wizard with more settings/controls for session. Good for scheduling future sessions.

learn more

featured sessions

@@ -47,7 +47,7 @@

Use the Find Sessions feature to browse through current and future/scheduled sessions you can join to play with other musicians.

- learn more + learn more
@@ -55,16 +55,14 @@

Use the Feed to check out current and past sessions and session recordings, and to listen to current sessions.

- learn more
-

learn more about online sessions

+

learn more about sessions

-

Use the following links to learn more:

- System Requirements & Gear Recommendations - Setting Up Your Gear - Key Features to Use for Online Sessions - Key Features to Use Beyond Online Sessions + Creating, finding, and joining sessions + Connecting with others + Playing with others in sessions + Live broadcasting your sessions
diff --git a/web/app/views/corps/cookie_policy.html.erb b/web/app/views/corps/cookie_policy.html.erb index 37d0b8136..2ba93ad9b 100644 --- a/web/app/views/corps/cookie_policy.html.erb +++ b/web/app/views/corps/cookie_policy.html.erb @@ -6,14 +6,34 @@

This Cookies Policy forms part of our general Privacy Policy. You can read the full Privacy Policy <%= link_to "here", corp_privacy_path %>.

In common with most other websites, we use cookies and similar technologies to help us understand how people use - JamKazam so that we can keep improving our Platform. We have created this Cookies Policy to provide you with clear and + JamKazam so that we can keep improving our Platform. We use + cookies for all or any of the following purposes:

+ +

We have created this Cookies Policy to provide you with clear and explicit information about the technologies that we use on JamKazam, and your choices when it comes to these technologies.

+ +

Consent to Cookies and Similar Technologies

If you choose to use the Platform without blocking or disabling cookies or opting out of other technologies, you will indicate your consent to our use of these cookies and other technologies and to our use (in accordance with this policy and the rest of our Privacy Policy) of any personal information that we collect using these technologies. If you do not consent to the use of these technologies, please be sure to block or disable cookies using your browser - settings and/or the settings within our mobile apps.

+ settings and/or the settings within our Apps. But, please note that if you choose to erase or block + cookies, you will need to re-enter your information to gain access to certain parts of the Platform + and may not be able to access other parts of the Platform (see the “Cookie Controls” section + below).

What are cookies?

Cookies are small text files that are placed on your computer by websites that you visit. These text files can be @@ -37,10 +57,9 @@

Google Analytics and Google Web Optimizer are services provided by Google, Inc. (“Google”). Google Analytics uses cookies to help us analyze how users use our website, our mobile site, our Apps, and any JamKazam widgets embedded on third party sites. Google Web Optimizer uses the same cookies to measure how different users respond to different - content. The information generated by these cookies (including your truncated IP address) is transmitted to and stored - by Google on servers in the United States. Google will use this information for the purpose of evaluating your, and - other users’, use of our website, mobile site, Apps, and JamKazam widgets, compiling reports for us on website - activity and providing other services relating to website activity and Internet usage. Please note that Google only + content. Google will use this information for the purpose of evaluating your and + other users’ use of our Platform, compiling reports for us on Platform + activity and providing other services relating to Platform activity and Internet usage. Please note that Google only receives your truncated IP address. This is sufficient for Google to identify (approximately) the country from which you are visiting our sites or accessing our players, but is not sufficient to identify you, or your computer or mobile device, individually.

@@ -56,29 +75,20 @@ our email newsletters. These clear GIFs tell us whether you opened the newsletter, clicked on any of the content or forwarded the newsletter to someone else. This provides us with useful information regarding the effectiveness of our email newsletters, which we can use to ensure that we are delivering information that is relevant to our users.

-

Support: We work with Desk.com, a subsidiary of Salesforce.com, (“Desk.com”) to provide support to our users, and we - use Desk.com’s identity integration to automate our users’ access to Desk.com support accounts, so that you do not - have to set up separate accounts for JamKazam support services. - Click here to review Desk.com’s privacy policy.

Cookie Controls

You can use the settings within your browser to control the cookies that are set on your computer or mobile device. However, please be aware that cookies are important to many aspects for the Platform – if you set your browser to - reject cookies, you may not be able to enjoy all of the features of the Platform. To find out how to see what cookies + reject cookies, you may not be able to enjoy all of the features of the Platform. Also, please note that the Platform may not respond to “do not track” + signals from browsers. Thus, your selection of the “do not track” option provided by your + browser may not have any effect on our collection of cookie information for analytic and internal + purposes. To find out how to see what cookies have been set and how to reject and delete cookies, please visit http://www.aboutcookies.org.

To opt-out of analysis by Google Analytics on our website and other websites, please visit http://tools.google.com/dlpage/gaoptout.

-

Consent to Cookies and Similar Technologies

-

We have done our best to provide you with clear and comprehensive information about our use of cookies and similar - technologies. If you choose to use the Platform without blocking or disabling cookies or opting out of these - technologies (as described above), you will indicate your consent to our use of these cookies and other technologies - and to our use (in accordance with this policy and our Privacy Policy) of any personal information that we collect - using these technologies. If you do not consent to the use of these technologies, please be sure to block or disable - them using your browser settings, and/or choose not to use the JamKazam service.

-
-

Effective Date: 1 August 2013

+

Effective Date: September 30, 2020

diff --git a/web/app/views/corps/privacy.html.erb b/web/app/views/corps/privacy.html.erb index fc9bc8a5f..89e063668 100644 --- a/web/app/views/corps/privacy.html.erb +++ b/web/app/views/corps/privacy.html.erb @@ -8,7 +8,7 @@

Your privacy is important to us. This Privacy Policy explains how we collect, store, use and disclose your personal information when you use jamkazam.com and m.jamkazam.com (together, the “Website”), our mobile and desktop apps (the "Apps") and all related sites, players, widgets, tools, apps, data, software, APIs and other services provided by - JamKazam (the “Services”).

+ JamKazam (the “Services”), as well as any personal information that you provide us, including through email.

This Privacy Policy explains the following:

@@ -30,7 +30,14 @@

By using the Website, the Apps or any of the Services, and in particular by registering a JamKazam account, you are - consenting to the use of your personal information in the manner set out in this Privacy Policy. + expressly consenting to the collection, use and disclosure of your personal information in the manner set out in this Privacy Policy. + This Privacy Policy is + incorporated into and subject to the Terms of Service (“Terms”), available here. Please take + some time to read this Privacy Policy (including the Cookies Policy), and make sure that you + find our use and disclosure of your personal information to be acceptable. If you do not agree to + any of the provisions of this Privacy Policy, you should not use the Website, the Apps or any of + the Services. If you have any questions or concerns, you can contact us + at  privacy@jamkazam.com.

@@ -39,23 +46,20 @@ and whenever we refer to the Privacy Policy, we are referring to the Privacy Policy incorporating the Cookies Policy.

-

- Please take some time to read this Privacy Policy (including the Cookies Policy), and make sure that you find our use - and disclosure of your personal information to be acceptable. -

- -

- If you do not agree to any of the provisions of this Privacy Policy, you should not use the Website, the Apps or any - of the Services. If you have any questions or concerns, you can contact us - at privacy@jamkazam.com. -

-

Please note that this Privacy Policy only applies to the Website, the Apps and the Services (together, the - “Platform”). When using the Platform, you may find links to other websites, apps and services, or tools that enable - you to share information with other websites, apps and services. JamKazam is not responsible for the privacy practices + “Platform”) and your provision of personal information to us by other means such + as email. When using the Platform, you may find links to other websites, apps and services, or tools that enable + you to share information with other websites, apps and services. For example, + you acknowledge that your access of any links to social media features on the Platform (e.g., + links to Facebook, Instagram, Twitter, etc.) is governed by the terms of use and privacy policies + of the companies providing such social media features. JamKazam is not responsible for the privacy practices of these other websites, apps and services and we recommend that you review the privacy policies of each of these - websites, apps or services before connecting your JamKazam account or sharing any personal information. + websites, apps or services before connecting your JamKazam account or sharing any personal information. The fact that a link to a third-party + website, app or service exists on the Platform does not mean that it operates under the same or + similar privacy practices as set forth in this Privacy Policy. The policies and procedures we + describe in this Privacy Policy do not apply to third-party websites, apps or services, and you + access them at your own risk.

Our Principles

@@ -72,7 +76,7 @@

You should have full control over your data

- We’ve designed the Platform to give you control over the information you publish and share using JamKazam and other + We’ve designed the Platform to give you control over the information you publish and share using the Platform and other sites and services to which you connect your JamKazam account. Please take full advantage of these tools and make sure you only share what you want to share.

@@ -107,16 +111,21 @@ or amended by you at any time. For more information, see the Choice and Control section below.

-
  • Information from Correspondence: You will provide certain personal information if you contact us by email, use any +
  • Information from Correspondence: You may provide certain personal information if you contact us by email, use any of the webforms on the Website, or contact us by mail, fax or other offline means.
  • -
  • Survey Information: If you participate in any survey, you will provide certain personal information as part of +
  • Survey Information: If you participate in any survey, you may provide certain personal information as part of your response, unless you respond anonymously.
  • Information that you post: You may provide personal information when you create or participate in sessions, make recordings, live broadcast sessions, post comments, participate on the support forums, or contribute to community discussions.
  • +
  • + Information from Sign-Ups or Opt-Ins: You may provide personal information such as + name and email address if you sign up for any publications, blogs, or newsletters that we + provide you, or on other sign-up or opt-in pages of the Platform. +
  • @@ -140,7 +149,9 @@
  • any search terms that you may enter on the Platform
  • the time, frequency and duration of your visits to the Platform
  • -
  • your browser type and operating system
  • +
  • your browser type and operating system (or, if you are accessing the Platform via a + mobile device, your mobile device unique number and mobile software and hardware + information)
  • the nature of the device from which you are accessing the Platform, for example, whether you are accessing the Platform from a personal computer or from a mobile device
  • @@ -161,10 +172,10 @@

    This information is collected by Facebook and is provided to us under the terms of Facebook’s privacy policy. You can control the information that we receive from Facebook using the privacy settings in your Facebook account.

    -

    If you sign up to JamKazam using Facebook, your JamKazam account will be connected automatically to your Facebook - account, and information regarding your activity on JamKazam, specifically any new sessions you create or join, any +

    If you sign up to the Platform using Facebook, your JamKazam account will be connected automatically to your Facebook + account, and information regarding your activity on the Platform, specifically any new sessions you create or join, any recordings you make, and any new favorites you save will be shared with Facebook and will be published in your - timeline and your Facebook friends’ newsfeeds. If you do not wish to share your JamKazam activity with your Facebook + timeline and your Facebook friends’ newsfeeds. If you do not wish to share your Platform activity with your Facebook friends, you can control this from your account settings on the Website and Apps – for more information, see the Choice and Control section below. If you signed up using Facebook by mistake, you can delete your account by emailing a request to do so to us @@ -176,23 +187,33 @@

  • Your email address and password are used to identify you when you log into the Platform.
  • Any additional information that you provide as part of your public profile, such as your real name, and links to your website and other social media profiles (but not your email address), will be published on your profile page. - This information will be publicly accessible and may be viewed by anyone accessing the Website, or using our API or + This information will be publicly accessible and may be viewed by anyone accessing the Website or Apps, or using our API or other Services. Please bear this in mind when considering whether to provide any additional information about yourself.
  • If you subscribe to a premium account, your name, address and payment verification information will be used to process your account subscription and to collect your payment. All payment verification information is transmitted - using industry-standard SSL (Secure Socket Layer) encryption. JamKazam also complies with the Payment Card Industry + using industry-standard SSL (Secure Socket Layer) encryption. This information is provided directly to third + party payment processors, and JamKazam does not store this information on its servers or + computer systems. JamKazam also complies with the Payment Card Industry Security Standards.
  • +
  • + If you purchase any JamTracks (as defined in the Terms of Service), then our third party + payment processor may process personal financial information such as name, phone + number, address, postal code, and credit card information for the purpose of completing + your purchase of such JamTracks. This information is provided directly to third party + payment processors, and JamKazam does not store this information on its servers or + computer systems. +
  • Your email address will be used to send you service updates and notifications regarding your account, and newsletters, marketing messages and certain email notifications from JamKazam.
  • If you are a Facebook user, and one of your Facebook friends registers for a JamKazam account, we will suggest to - your Facebook friend that you might be someone they may wish to connect with as a friend or follow on JamKazam. + your Facebook friend that you might be someone they may wish to connect with as a friend or follow on the Platform.
  • If you are a Facebook user and sign up using Facebook, we may also use the information we receive about you from - Facebook to suggest users that you may wish to connect with as a friend or follow on JamKazam. It will be up to you + Facebook to suggest users that you may wish to connect with as a friend or follow on the Platform. It will be up to you if you choose to connect with or follow these users and you can disconnect or unfollow them at any time.
  • @@ -216,16 +237,16 @@ recordings.
  • To analyze the use of the Platform, and the people visiting the Website and using the Apps and Services, in order - to improve JamKazam. + to improve the Platform.
  • To respond to you about any comment or inquiry you have submitted.
  • To customize your use of the Platform and/or the content of any email newsletter or other material that we may send to you from time to time.
  • To prevent or take action against activities that are, or may be, in breach of - our <%= link_to "Terms of Service", corp_terms_path %> or applicable law. + our <%= link_to "Terms of Service", corp_terms_path %>, this Privacy Policy, or applicable law.
  • -
  • For other purposes, provided we disclose this to you at the relevant time, and provided that you agree to the +
  • For other purposes, provided we disclose this to you at the relevant time, and provided that you consent to the proposed use of your personal information.
  • @@ -243,18 +264,21 @@ that they can track the popularity of their sessions and recordings. Similarly, if you comment on any sessions or recordings on the Platform, your comments will be available to all users of the Platform. -
  • With your consent: We will disclose your personal information if you have explicitly agreed that we may do so. We +
  • With your consent: We will disclose and share your personal information if you have explicitly agreed that we may do so. We will make this clear to you at the point at which we collect your information.
  • Service Providers: We use certain reputable third parties, some of whom may be located outside of the United States, to provide us with certain specialized services related to the Platform. These third parties will have access to certain information about you, but only where this is necessary in order for those third parties to - provide their services to us. Where we transfer personal information to these third parties, we ask and require + provide their services to us. Where we transfer personal information to these third parties, we use commercially reasonable efforts to require these third parties to implement appropriate organizational and technical security measures to protect against unauthorized disclosure of personal information, and only to process personal information in accordance with our - instructions and to the extent necessary to provide their services to us. + instructions and to the extent necessary to provide their services to us. However, since + we do not control third party service providers, we make no representations or warranties + about the acts or omissions of third party service providers, including whether such + parties will always keep information confidential.
  • -
  • Users of our API: JamKazam has an open API, which enables application developers to integrate elements of the +
  • Users of our API: The Platform has an API, which may enable application developers to integrate elements of the Platform into exciting new apps. Some of these developers may be located outside of the United States. Any personal information that you choose to make public on the Platform, including your public profile information and any public sessions and recordings, may be accessible to these developers. Please bear this in mind when deciding what @@ -263,7 +287,7 @@
  • Other networks and connected apps: If you choose to connect your JamKazam account to other apps or social networks such as Facebook, Google+, or Twitter, you will be sharing certain information with these apps or networks. In the - case of Facebook, Google+, or Twitter, any new public sessions or recordings that you participate in on JamKazam or + case of Facebook, Google+, or Twitter, any new public sessions or recordings that you participate in on the Platform or any new favorites you save will be shared to those networks and will be visible to your followers and friends on those networks. JamKazam is not responsible for these other apps or networks, so please make sure you only connect your account with apps or services that you trust. For information on how to control the information that your @@ -276,7 +300,10 @@ contact information, or anything that could be used to identify you individually, either online or in real life.
  • If required by law: We will disclose your personal information if we believe in good faith that we are permitted - or required to do so by law, including in response to a court order, subpoena or other legal demand or request. + or required to do so by law, including in response to a court order, subpoena or other legal demand or request (including requests from law enforcement). + We also may disclose personal information if we believe it is necessary to investigate, + prevent or take action regarding illegal activities, suspected fraud, or situations involving + potential threats to the physical safety of any person.
  • To protect our interests: We may disclose your personal information if we feel this is necessary in order to protect or defend our legitimate rights and interests, or those of our users, employees, directors or shareholders, @@ -284,7 +311,11 @@
  • In the context of a business transfer: We may transfer your personal information to any person or company that acquires all or substantially all of the assets or business of JamKazam, or on a merger of our business, or in the - event of our insolvency. + event of our insolvency. We make + no guarantee as to whether any entity purchasing JamKazam’s assets or business, or + merging with JamKazam, will treat your information in the same manner as is disclosed + in this Privacy Policy, and we disclaim all liability arising out of such entity’s failure to + do so.
  • @@ -318,12 +349,12 @@ to your sessions and recordings.

    Sharing with other apps and networks

    -

    The Integrations section of the Account feature enables you to control the information you share with other networks +

    The Profile section of your account enables you to control the information you share with other networks and applications. As well as selecting those of your social networks you wish to share to, you can also control access to other services and applications to which you have connected your JamKazam account.

    -

    If you sign up for JamKazam using your Facebook account, your JamKazam account and your Facebook account will be +

    If you sign up for a JamKazam account using your Facebook account, your JamKazam account and your Facebook account will be connected automatically. Information regarding the public sessions and recordings that you participate in and - recordings you favorite on JamKazam will be shared with the connected Facebook account. Content that you share with + recordings you favorite on the Platform will be shared with the connected Facebook account. Content that you share with Facebook will appear on your timeline and in your Facebook friends’ newsfeeds. If you do not want this information shared with Facebook, please change your account settings.

    Please note that this Privacy Policy does not apply to any third party sites or applications, and we cannot control @@ -332,21 +363,16 @@ sites or applications.

    Sharing with app developers

    -

    JamKazam has an open API, which allows third party developers to build some really cool apps as an extension of the +

    JamKazam may have an API, which may allow third party developers to build apps as an extension of the Platform. If you would prefer that your sessions and recordings are not made available to third party app developers, you can disable API access in the Integrations section of your account settings. Please note that your public profile information will still be accessible, but this does not include anything that this not publicly available on the Website.

    -

    Cookies

    -

    Information on how to block or disable cookies is included in our <%= link_to "Cookies Policy", corp_cookie_policy_path %> - . Further information about cookies in general is available at - http://aboutcookies.org

    -

    Deleting your account

    You can delete your account from the JamKazam Platform by sending an email requesting account deletion from the email address associated with your account to support@jamkazam.com. - Please bear in mind that, if you delete your account, all data associated with your account, including the sounds that + Please bear in mind that, if you delete your account, all data associated with your account, including the sounds and content that you have uploaded and the usage data associated with those sounds will no longer be available to you or others. You are therefore advised to copy or back up all content uploaded to your account before you delete your account.

    Even if you delete your JamKazam account, it is possible that your information may still show up in some internet @@ -358,13 +384,19 @@

    Please note that deleting any JamKazam Apps, or any third party apps to which your JamKazam account is connected, will not delete your JamKazam account. If you wish to delete your account, you will need to do so as described above.

    +

    + If you do not delete your account (or do not request deletion of your personal information as + described in the “Access to your Data” section below), we may, except where required otherwise + by applicable law, indefinitely store your information; provided that we reserve the right to + delete such information for any reason or for no reason. +

    Access to your Data

    As described above, most of the personal information you provide to us can be accessed and updated in the Profile and - Account pages of the JamKazam Website and Apps. If you wish to access, amend or delete any other personal information + Account pages of the Platform. If you wish to access, amend or delete any other personal information we hold about you, or if you have any objection to the processing of any information that we hold about you, please - contact us at privacy@jamkazam.com, or the address provided - below.

    + contact us at privacy@jamkazam.com. Changes to your account may, in + some case, require a fee to be paid by you to cover our costs.

    If you ask us to delete your account, we will do so within a commercially reasonable period of time, but we may need to retain some of your personal information in order to satisfy our legal obligations, or where we have a legitimate reason for doing so.

    @@ -376,22 +408,161 @@ to the laws in the U.S., and by using the Platform, you consent to the transfer, storage and processing of your personal information outside the United States in accordance with this Privacy Policy and applicable law.

    -

    Children

    -

    JamKazam is not intended for use by children. Anyone under the age of 13 is not permitted to use the Platform and - must not attempt to register an account or submit any personal information to us. We do not knowingly collect any - personal information from any person who is under the age of 13 or allow them to register an account. If it comes to - our attention that we have collected personal data from a person under the age of 13, we will delete this information - as quickly as is commercially reasonable. If you have reason to believe that we may have collected any such data, - please notify us immediately at privacy@jamkazam.com.

    +

    Children's Privacy

    +

    As a general rule, JamKazam is not intended for use by children, and anyone under the age of 13 is generally not permitted to use the Platform. + Notwithstanding the foregoing, + in some cases, we work with partners that provide the Platform as part of music program + offerings (including those listed below) to children under 13, and we sell the Platform directly to + some schools that use the Platform for the benefit of, and allow use of the Platform by, children + under 13. In such cases, we rely on these partners and/or schools to obtain verified parental + consent required by COPPA from parents or guardians of such children under 13 so that + JamKazam can either directly collect information from such children or so that JamKazam can + receive such information from the applicable partner or school that collected such information. + We rely on such partners and/or schools to obtain this consent before JamKazam directly collects + personal information from such children, or before the partner or school provides such + information to JamKazam (as applicable). Such personal information collected regarding + children under 13, whether collected directly or indirectly by JamKazam consists of: +

    + +

    + Currently, the partners we work with to provide music program offerings that include the + Platform to children under 13 include: +

    + +

    + If you are a parent or guardian of a child under 13 that participates in a music program including + the Platform or that attends a school whereby the Platform will be provided to such child, you + must provide verified parental consent for your child to use the Platform, and you must be the + actual parent or guardian of the child in order to legally grant such consent under COPPA. You + may revoke your consent at any time or refuse to allow further personal information collection + about your child by contacting us at privacy@jamkazam.com (in addition to contacting the + applicable school or partner providing the music program where the Platform is being + used)—upon receipt of this request, we will delete any unaggregated, non-anonymized personal + information we have in our possession regarding your child, and you and your child will not + provide us with any more personal information thereafter (note, however, that JamKazam may + suspend you and your child’s ability to use the Platform indefinitely, until a new verified parental + consent is received by the applicable school or partner). You may also contact us at the same + email address in order to view, verify, and change or update any personal information collected + by JamKazam about your child. Any personal information from children under the age of 13 + that is collected by JamKazam as described herein is done solely to provide the Platform to + partners and schools using the Platform for such children, as well as the individual children + themselves that are participating in the music programs and classes provided by such partners + and schools. We do not collect more personal information from children under 13 than is + necessary for us to do the foregoing. JamKazam will not share such personal information with + any third parties, other than the parent(s) of the applicable child, or the school or partner + providing the music program or class in which the child attends. JamKazam requires such + partners and schools to comply with COPPA. Except as set forth in this “Children’s Privacy” + section, JamKazam does not otherwise knowingly solicit any personal information directly from, + or otherwise knowingly use or disclose personal information of, children under the age of 13. In + the If JamKazam is made aware that JamKazam has collected personal information from a child + under 13 years old in a manner that is inconsistent with the Children’s Online Privacy Protection + Act of the United States (“COPPA”), then we will delete this information as soon as practicable. +

    +

    Special Terms Regarding Data Collected from California Residents

    +

    + The California Consumer Privacy Act (“CCPA”) provides some California residents with certain + additional rights, each of which is summarized in this section of this Privacy Policy. “You” as + used in this section shall mean a user to whom the CCPA applies. +

    +

    + Right to Know. Under the CCPA, you have the right to know what data we have collected about + you over the past year, including: +

    + -

    Changes and Updates to this Privacy Policy

    + +

    + Right to Delete. Under the CCPA, you have the right to request that we delete the personal + information we have collected from you (and direct our third party service providers to also + delete such personal information). However, the CCPA has several exceptions to this right to + delete, including without limitation when the information is necessary for us or a third party to: +

    + + + +

    + Other Rights. You can request certain information about our disclosure of personal information + to third parties for their own direct marketing purposes during the preceding calendar year. This + request is free and may be made one (1) time per calendar year. You also have the right not to be + discriminated against for exercising any of the rights listed above. +

    +

    + To exercise any of the rights summarized above under the CCPA, please contact us via e-mail at + privacy@jamkazam.com . Please include your full name, email address, and phone number + associated with your use of the Platform, along with why you are writing, so that e can process + your request in an efficient manner. JamKazam aims to respond to such a request within 10 + days of receiving such request. If we require more time, we will inform you of the reason and + extension period in writing. +

    +

    Notice Regarding Non-US Users of the Platform

    +

    + Please note that the Platform is hosted in the United States. If you choose to use the Platform + from the European Union or other regions of the world with laws governing data collection and + use that may differ from U.S. law, then please note that you are transferring your personal + information outside of those regions to the United States for storage and processing and that the + privacy laws in the United States may offer fewer protections than those of your home country. +

    +

    Changes and Updates to this Privacy Policy

    We may occasionally update this Privacy Policy, and when we do so, we will also revise the Effective Date set out below. Any changes to our Privacy Policy will always be available here so that JamKazam users are always aware of what information we gather, and how we might use and share that information. Please be sure to check back here from time to time to ensure that you are aware of any changes to this Privacy Policy. Any material changes to this Privacy Policy will be communicated to registered users by a notification to their account and/or by posting a notice of the change - on the Website.

    - + on the Platform.

    +

    Security

    +

    + Although JamKazam takes reasonable measures to ensure the security of the data you may + choose to provide us from loss or misuse, unfortunately the transmission of data through the + Internet cannot be guaranteed to be 100% secure. JamKazam nor any of its respective + employees, officers or agents or the provider of the internet services on behalf of JamKazam (nor + any other person involving the management or establishment of the Platform) can give any + representation or warranty as to the absolute security of the data transmitted using the Platform + and cannot give any guarantee that such data will not be compromised by bad actors. JamKazam + also assumes no responsibility for loss of information, howsoever such information is lost, + including information which is permanently deleted either through the actions of an employee or + consultant or other who has access to the information, through failures of a computer network, or + through any policy or directive of JamKazam for archival and destruction of data. If you choose + to provide data to or allow collection of data by JamKazam, then you do so understanding the + aforementioned risks. +

    +

    Disputes

    +

    + For disputes regarding our collection or use of your personal information or for more + information, or questions or comments concerning this Privacy Policy, please see our Terms of + Service or contact us via email at privacy@jamkazam.com. +

    Questions?

    If you have questions about this Privacy Policy, want to suggest changes to this Privacy Policy or want to know, what information we store about you, please contact us by email @@ -402,11 +573,14 @@ (including our <%= link_to "Cookies Policy", corp_cookie_policy_path %>), please do not use the Platform. If you have already registered an account, you can cancel your account by sending an email from the email address associated with your account, requesting deletion of your account, to - privacy@jamkazam.com.

    + privacy@jamkazam.com. + You may also opt-out of promotional and marketing + communications by emailing us at the aforementioned address. +


    Last amended:
    - 1 August 2013 + 30 September 2020

    \ No newline at end of file diff --git a/web/app/views/corps/terms.html.erb b/web/app/views/corps/terms.html.erb index a4177e847..37a35f7d1 100644 --- a/web/app/views/corps/terms.html.erb +++ b/web/app/views/corps/terms.html.erb @@ -14,7 +14,7 @@ +

    + Note that the headings used in these Terms are for convenience only and have no legal meaning + or effect. Terms defined in the singular have the corresponding meanings in the plural, and vice + versa. Unless the context of these Terms clearly requires otherwise, words importing the + masculine gender include the feminine and neutral genders and vice versa. The terms “include,” + “includes” or “including” mean “including without limitation.” The words “hereof,” “hereto,” + “hereby,” “herein,” “hereunder” and words of similar import, when used in these Terms, refer to + these Terms as a whole and not to any particular section or article in which such words appear. + The word “or” will not be construed as exclusive. +

    Acceptance of Terms

    @@ -162,12 +176,11 @@ , and <%= link_to "Cookies Policy", corp_cookie_policy_path %> carefully.  Our Privacy Policy and Cookies Policy are hereby incorporated by reference into these Terms. If you do not agree to any of - the provisions set out in those documents, you should not use the Website, Apps or any of the Services. By accessing + the provisions set out in these Terms, you may not use the Website, Apps or any of the Services. By accessing or using the Platform, registering an account, or by viewing, accessing, streaming, uploading or downloading any information or content from or to the Platform, you represent and warrant that you have read and understood the Terms, - will abide by them, and that you are either 18 years of age or more, + will abide by these Terms and are legally entitled to enter into these Terms, and that you are either 18 years of age or more, or you are 13 years of age or more and have your parent(s)’ or legal guardian(s)’ permission to use the Platform. - THE PLATFORM IS NOT FOR CHILDREN UNDER THE AGE OF 13. IF YOU ARE UNDER THE AGE OF 13, THEN YOU ARE NOT PERMITTED TO USE THE SERVICE. If you are accessing the Platform on behalf of an entity or organization (collectively, “Organization”), then you represent and warrant that (a) you are an authorized representative of that Organization, @@ -179,14 +192,17 @@

    Changes to Terms

    We reserve the right to change, alter, replace or otherwise modify these Terms at any time; - provided however, that we will endeavor to provide you with material notice of any prior changes. The date of + provided however, that we will use reasonable efforts to provide you with notice of any material changes (of which such notice may include any notice posted on the + Platform). The date of last modification is stated at the end of these Terms. It is your responsibility to check this page from - time to time for updates. + time to time for updates. By continuing to access or use + any of the Website, Apps, and/or Services after these Terms have been revised, you agree to be + bound by the revised Terms.

    Description of the Platform

    The Platform is a hosting service. Registered users of the Platform may submit, upload and post text, photos, - pictures, comments, and other content, data or information, and may perform, stream, broadcast, and record musical + pictures, videos, files, links, comments, and other content, data or information, and may perform, stream, broadcast, and record musical pieces (“Content”), which will be broadcast, stored, displayed and/or played by JamKazam at the direction of such registered users, and may be shared and distributed by such registered users, and other users of the Platform, using the tools and features provided as part of the Platform and accessible via the Website, Apps and elsewhere. The @@ -194,11 +210,15 @@ user of the Website, Apps or certain Services (who may or may not be registered users of the Platform) to view, listen to and share Content uploaded and otherwise made available by registered users.

    We may, from time to time, release new tools and resources on the Website, release new versions of our Apps, or - introduce other services and/or features for the Platform. Any new services and features will be subject to these - Terms as well as any additional terms of service that we may release for those specific services or + introduce other Services and/or features for the Platform. Any new Services and features will be subject to these + Terms as well as any additional terms of service that we may release for those specific Services or features.

    -

    JamKazam owns or has rights to all of the content we make available through the Platform, - but you may use it as you use the Platform. You may not use our logo without our written permission.

    +

    JamKazam owns or has rights to the Platform and Materials (as defined below) and all intellectual property therein,, + but you may use the Platform in accordance with these Terms (including as described in + the license set forth in the “Your Use of the Platform” section below). You may not copy, distribute, transmit, publish, sell, transfer, or + create derivative works of the Platform. If you print any paper or digital copies of pages of the + Website, you may only do so for your internal use and you are prohibited from removing any + copyright or other proprietary notices on such pages.

    The contents of the Platform include: designs, text, graphics, images, video, information, logos, button icons, software, audio files, computer code, and other JamKazam content (collectively, “Materials”). All Materials and the compilation (meaning the collection, arrangement, and assembly) of all Materials are the @@ -209,38 +229,47 @@ you agree not to display or use the JamKazam Marks in any manner.

    Your JamKazam Account

    -

    You are not obliged to register to use the Platform. However, access to the Apps and certain Services is only +

    You are not obligated to register an account to use the Website and certain aspects of the + remainder of the Platform.. However, access to the Apps and certain Services is only available to registered users.

    -

    When you register to use the Platform, you will provide us with your name, email address, instruments played, and +

    When you register to use the Platform, you will provide us with your name and email address and will choose a password for your account. You must ensure that the email address that you provide is, and remains, - valid. Your email address and any other information you choose to provide about yourself will be treated in accordance + valid, and you shall only provide accurate, true and + current information as part of the account registration process (and you agree to keep such + information current at all times). Your email address and any other personal information you choose to provide about yourself will be treated in accordance with our <%= link_to "Privacy Policy", corp_privacy_path %>.

    You are solely responsible for maintaining the confidentiality and security of your password, and you will remain - responsible for all use of your password, and all activity emanating from your account, whether or not such activity + responsible for all use of your password, and all activity emanating from your account (including any Content posted via your account), whether or not such activity was authorized by you.

    If your password is lost or stolen, or if you believe that your account has been accessed by unauthorized third - parties, you are advised to notify JamKazam in writing, and should change your password at the earliest possible + parties, you must immediately notify JamKazam in writing, and you must change your password at the earliest possible opportunity.

    -

    We reserve the right to, with or without prior notice, suspend or terminate your account if activities occur on that +

    We reserve the right to, with or without prior notice, suspend or terminate your account and your ability to use the Platform if activities occur on that account which, in our sole discretion, would or might constitute a violation of these Terms, or an - infringement or violation of the rights of any third party, or of any applicable laws or regulations.

    + infringement or violation of the rights of JamKazam or any third party, or a violation of any applicable laws or regulations. + We reserve + the right to bring legal action against you for any loss or damage that we may suffer as a result of + your violation of these Terms, your infringement of any JamKazam or third party rights, and + your violation of any applicable law or regulation. We also may terminate or suspend use + of the Platform for any person or entity for any reason. +

    You may terminate your account at any time as described in the Termination section below.

    Your Use of the Platform

    Subject to your strict compliance with these Terms, JamKazam grants you a limited, personal, - non-exclusive, revocable, non-assignable and non-transferable right and license to use the Platform in order to view + non-exclusive, revocable, non-assignable, non-sublicensable and non-transferable right and license to use the Platform in order to view Content uploaded and posted to the Platform, to listen to audio Content streamed from the Platform and to share and download audio Content using the features of the Platform where the appropriate functionality has been enabled by the user who uploaded or created the relevant audio Content (the “Uploader”).

    In addition, if you register to use the Platform, and subject to your strict compliance with these Terms, - JamKazam grants you a limited, personal, non-exclusive, revocable, non-assignable and non-transferable right and + JamKazam grants you a limited, personal, non-exclusive, revocable, non-assignable, non-sublicensable and non-transferable right and license to: (i) participate in sessions, make recordings, and submit, upload or post other Content to the Platform strictly as - permitted in accordance with these Terms and any other applicable terms posted on the Website and Apps from + permitted in accordance with these Terms and any other applicable terms posted on the Platform from time to time; (ii) participate in the community areas and communicate with other members of the JamKazam community strictly in accordance with these Terms; and (iii) use our Apps and other Services provided as part of the Platform strictly as permitted in accordance with these - Terms of Service and any other terms applicable to those Apps or Services from time to time.

    + Terms and any other terms applicable to those Apps or Services from time to time.

    The above licenses are conditional upon your strict compliance with these Terms, including, without limitation, the following:

      @@ -251,10 +280,12 @@ transfer, share, distribute or otherwise use or exploit any Content on or from the Platform, except (i) where such Content is Your Content, or (ii) as permitted under these Terms, and within the parameters set by the Uploader (for example, under the terms of Creative Commons licenses selected by the Uploader). -
    1. You must not use any Content (other than Your Content) in any way that is designed to create a separate content +
    2. You must not use any Content in any way that is designed to create a separate content service or that replicates any part of the Platform offering.
    3. You must not employ scraping or similar techniques to aggregate, repurpose, republish or otherwise make use of - any Content.
    4. + any Content. You also may not use spiders, robots, avatars, + intelligent agents, or any other extraction or navigation search except for a normal + browser when retrieving information from the Platform.
    5. You must not employ any techniques or make use of any services, automated or otherwise, designed to misrepresent the popularity of Your Content on the Platform, or to misrepresent your activity on the Platform, including without limitation by the use of bots, botnets, scripts, apps, plugins, extensions or other automated means to register @@ -262,11 +293,11 @@ comments, or otherwise to act on your behalf, particularly where such activity occurs in a multiple or repetitive fashion. You must not offer or promote the availability of any such techniques or services to any other users of the Platform.
    6. -
    7. You must not alter or remove, attempt to alter or remove, any trademark, copyright or other proprietary or legal +
    8. You must not alter or remove, or attempt to alter or remove, any trademark, copyright or other proprietary or legal notices contained in, or appearing on, the Platform or any Content appearing on the Platform (other than Your Content).
    9. -
    10. You must not, and must not permit any third party to, copy or adapt the object code of the Website or any of - the Apps or Services, or reverse engineer, reverse assemble, decompile, modify or attempt to discover any source or +
    11. You must not, and must not permit any third party to, copy or adapt the object code of the Platform, + or reverse engineer, reverse assemble, decompile, modify or attempt to discover any source or object code of any part of the Platform, or circumvent or attempt to circumvent or copy any copy protection mechanism or access any rights management information pertaining to Content other than Your Content.
    12. You must not use the Platform to perform, record, upload, post, store, transmit, display, copy, distribute, @@ -277,8 +308,8 @@ race, gender, religion or sexual orientation, or is otherwise objectionable in JamKazam’s reasonable discretion;
    13. any information, Content or other material that violates, plagiarises, misappropriates or infringes the rights of - third parties including, without limitation, copyright, trademark rights, rights of privacy or publicity, - confidential information or any other right; + third parties including, without limitation, copyright, trademark rights, rights of privacy or publicity, rights in + trade secrets or confidential information or any other right;
    14. any Content that violates, breaches or is contrary to any law, rule, regulation, court order or is otherwise is illegal or unlawful in JamKazam’s reasonable opinion; @@ -300,8 +331,7 @@ person or entity, for example, by registering an account in the name of another person or company, or sending messages or making comments using the name of another person.
    15. You must not stalk, exploit, threaten, abuse or otherwise harass another user, or any JamKazam employee.
    16. -
    17. You must not use or attempt to use another person's account, password, or other information, unless you have - express permission from that other person.
    18. +
    19. You must not use or attempt to use another person's account, password, or other information.
    20. You must not sell or transfer, or offer to sell or transfer, any JamKazam account to any third party without the prior written approval of JamKazam.
    21. You must not collect or attempt to collect personal data, or any other kind of information about other users, @@ -310,11 +340,16 @@ JamKazam or any Uploader; access or attempt to access data or materials which are not intended for your use; log into, or attempt to log into, a server or account which you are not authorized to access; attempt to scan or test the vulnerability of JamKazam’s servers, system or network or attempt to breach JamKazam’s data security or authentication - procedures; attempt to interfere with the Website or the Services by any means including, without limitation, hacking + procedures; attempt to interfere with the Platform by any means including, without limitation, hacking JamKazam’s servers or systems, submitting a virus, overloading, mail-bombing or crashing. Without limitation to any other rights or remedies of JamKazam under these Terms, JamKazam reserves the right to investigate any situation that appears to involve any of the above, and may report such matters to, and co-operate with, appropriate law enforcement authorities in prosecuting any users who have participated in any such violations.
    22. +
    23. + You acknowledge that standard SMS and data fees may apply when accessing the + Platform via a mobile device. [To opt out of SMS notification associated with the + Platform, please contact us at privacy@jamkazam.com]. +

    You agree to comply with the above conditions, and acknowledge and agree that JamKazam has the right, in its sole @@ -325,25 +360,39 @@

    Purchasing JamTracks

    The Platform may allow you to purchase multi-track recordings (“JamTracks”) . - JamTracks are licensed and not sold to you. You may only use JamTracks for your own personal, - non-commercial use and not for any other purpose. Except as permitted by applicable law, you may not reproduce - (except on computer equipment or personal digital devices (e.g., phones, tablets, MP3 players, etc.) owned or controlled by you), - or distribute any JamTracks obtained from or through the Platform without JamKazam’s - or the applicable copyright owner’s express permission. - JamTracks that are streamed to you are also licensed to you solely for personal, non-commercial use. - JamTracks are made available to you for the price set forth on the Platform. - All purchases for JamTracks are final, and no refunds are available. - Payments must be made by credit card through our third party payment processor. - All payments are made in United States Dollars. + JamTracks are + licensed and not sold to you. You may only use JamTracks for your own personal, non- + commercial use and not for any other purpose. Except as permitted by applicable law, you may + not reproduce (except on computer equipment or personal digital devices (e.g., phones, tablets, + MP3 players, etc.) owned or controlled by you), or distribute any JamTracks obtained from or + through the Platform without JamKazam’s or the applicable copyright owner’s express + permission. JamTracks are made available to you for the price set forth on the Platform. ). + Pricing information displayed is subject to change, and we may increase or decrease fees as we + deem necessary. In addition, we have no control of fee adjustments made by third parties. All + purchases for JamTracks are final, and no refunds are available (provided that JamKazam may + choose whether to grant them in its sole and absolute discretion). Payments must be made by + credit card through our third party payment processor, and as a condition to purchasing + JamTracks, you agree to provide a valid credit card and pay for all JamTracks that you request + for purchase. All payments are made in United States Dollars. You expressly authorize + JamKazam and its third party payment processor to charge the payment method you provide for + any purchased JamTracks. You also expressly authorize JamKazam to set the prices for all + charges and fees that apply to the provision of such JamTracks. Your selection of the + [“Confirm”] button on the checkout page for JamTracks purchases is your electronic signature + and you agree that (a) this signature is the legal equivalent of your wet or manual signature and + (b) this transaction is equivalent to an in-person transaction where your payment method is + physically present.

    Your Content

    -

    Any and all audio, text, photos, pictures, graphics, comments, and other content, data or information that you - perform, record, upload, store, transmit, submit, exchange or make available to or via the Platform (hereinafter “Your +

    Any and all Content that you + perform, record, upload, store, transmit, submit, exchange or make available to or via the Platform + or that you provide to JamKazam by any means, including via email (hereinafter “Your Content”) is generated, owned and controlled solely by you, and not by JamKazam.

    JamKazam does not claim any ownership rights in Your Content, and you hereby expressly acknowledge and agree that - Your Content remains your sole responsibility.

    + Your Content remains your sole responsibility. You shall be solely + responsible for keeping a duplicate copy of all Your Content, and JamKazam accepts no + responsibility or liability for the loss or deletion of Your Content.

    Without prejudice to the conditions set forth in Your Use of the Platform you must not perform, record, upload, store, distribute, send, transmit, display, make available or otherwise communicate to the public any Content to which you do not hold the necessary rights. In particular, any unauthorized use of @@ -353,27 +402,26 @@ prohibited. Any such infringements may result in termination of your access to the Platform as described in the Repeat Infringers section below, and may also result in civil litigation or criminal prosecution by or on behalf of the relevant rights holder.

    -

    We may, from time to time, invite or provide you with means to provide feedback regarding the Platform, and in such - circumstances, any feedback you provide will be deemed non-confidential and JamKazam shall have the right, but not the - obligation, to use such feedback on an unrestricted basis.

    Grant of License

    -

    By performing, recording, uploading, posting, or otherwise transmitting Your Content to the Platform, you initiate an +

    By performing, recording, uploading, posting, or otherwise transmitting Your Content to the Platform or otherwise providing any of Your Content to JamKazam, you initiate an automated system to process any such Content, including but not limited to audio, graphic, and textual Content, and direct JamKazam to store Your Content on our servers, from where you may control and authorize the use, reproduction, transmission, distribution, public display, public performance, making available and other communication to the public of Your Content on the Platform and elsewhere using the Services. To the extent it is necessary in order for JamKazam to provide you with any of the aforementioned hosting services, to undertake any of the tasks set forth in these Terms - and/or to enable your use of the Platform, you hereby grant such licenses to JamKazam on a limited, - worldwide, non-exclusive, royalty-free and fully paid basis.

    + and/or to enable your use of the Platform, you hereby grant to JamKazam a limited, + worldwide, non-exclusive, sublicensable, transferable, royalty-free and fully paid license to use, copy, repost, transmit or otherwise distribute, publicly display, + publicly perform, adapt, prepare derivative works of, compile, make available and otherwise + communicate to the public, Your Content when operating the Platform.

    By performing, recording, uploading, posting, or otherwise transmitting Your Content to the Platform, you also grant a limited, worldwide, non-exclusive, royalty-free, fully paid up license to other users of the Platform, and to operators and users of any other websites, apps and/or platforms to which Your Content has been shared or embedded using the Services (“Linked Services”), to use, copy, repost, transmit or otherwise distribute, publicly display, publicly perform, adapt, prepare derivative works of, compile, make available and otherwise communicate to the public, Your Content utilizing the features of the Platform from time to time, and within the parameters set by you using the - Services. You can limit and restrict the availability of certain of Your Content to other users of the Platform, and + Platform. You can limit and restrict the availability of certain of Your Content to other users of the Platform, and to users of Linked Services, at any time using the settings available in the account features of the Website and Apps, subject to the provisions of the Disclaimer section below. Notwithstanding the foregoing, nothing in these Terms grants any rights to any other user of the Platform with respect to any proprietary @@ -388,27 +436,25 @@ irrevocable, and will continue notwithstanding any termination of your account. However, notwithstanding the foregoing, you hereby acknowledge that any of Your Content that was created and stored on the Platform in conjunction with other users of the Platform, including but not limited to sessions and recordings, may be maintained on the - Platform until and unless all other users who participated in the creation of such Content also take action to remove + Platform and stored on + JamKazam’s servers until and unless all other users who participated in the creation of such Content also take action to remove such Content from their accounts. (For purposes of clarity, the reason for this is that otherwise one user could, for example, force the removal of a musical recording made with multiple other users when those other users do not want the recording removed.)

    -

    Removal of audio Content from your account will automatically result in the disassociation of such Content from your - account, but it will not result in the deletion of the relevant files from JamKazam’s systems and servers until or - unless all other users who participated in the creation of such audio Content also request removal of such Content. - Notwithstanding the foregoing, you hereby acknowledge and agree that once Your Content is distributed to a Linked +

    Notwithstanding the foregoing, you hereby acknowledge and agree that once Your Content is distributed to a Linked Service, JamKazam is not obligated to ensure the deletion of Your Content from any servers or systems operated by the operators of any Linked Service, or to require that any user of the Platform or any Linked Service deletes any item of Your Content.

    Any Content other than Your Content is the property of the relevant Uploader, and is or may be subject to copyright, trademark rights or other intellectual property or proprietary rights. Such Content may not be downloaded, reproduced, distributed, transmitted, re-uploaded, republished, displayed, sold, licensed, made available or otherwise - communicated to the public or exploited for any purposes except via the features of the Platform from time to time and + communicated to the public or exploited for any purposes by you except via the features of the Platform from time to time and within the parameters set by the Uploader on the Platform or with the express written consent of the Uploader. Where you repost another user’s Content, or include another user’s Content in a set, you acquire no ownership rights whatsoever in that Content. Subject to the rights expressly granted in this section, all rights in Content are reserved to the relevant Uploader.

    You hereby waive any and all moral rights in and to Your Content in connection with JamKazam’s and other users’ use of Your Content as authorized by you.

    -

    We appreciate hearing from our users and welcome your comments regarding the Platform. Please be advised, however, that if you send us creative ideas, suggestions, inventions, or materials (“Creative Ideas”), we will: +

    We appreciate hearing from our users and welcome your comments regarding the Platform. Please be advised, however, that if you send us creative ideas, feedback, suggestions, inventions, or materials (“Creative Ideas”), we will:

    1. own, exclusively, all now known or later discovered rights to the Creative Ideas;
    2. not be subject to any obligation of confidentiality and will not be liable for any use or disclosure of any @@ -425,7 +471,7 @@ store, transmit, distribute, share, publicly display, publicly perform, make available and otherwise communicate to the public Your Content, and each and every part thereof, on, through or via the Website, Apps, any and all Services and any Linked Services.
    3. -
    4. Your Content and the availability thereof on the Platform does not and will not infringe or violate the rights +
    5. Your Content and the availability thereof on the Platform does not and will not infringe, misappropriate or violate the rights of any third party, including, without limitation, any intellectual property rights, performers’ rights, rights of privacy or publicity, or rights in confidential information.
    6. You have obtained any and all necessary consents, permissions and/or releases from any and all persons @@ -456,7 +502,7 @@ Content that is inappropriate, that does or might infringe any third party rights, or has otherwise been performed, recorded, entered, or uploaded in breach of these Terms or applicable law.

      JamKazam and its subsidiaries, affiliates, successors, assigns, employees, agents, directors, officers and - shareholders hereby exclude, to the fullest extent permitted by law, any and all liability which may arise from any + shareholders hereby exclude and disclaim, to the fullest extent permitted by law, any and all liability which may arise from any Content performed, recorded, entered, or uploaded to the Platform by users, including, but not limited to, any claims for infringement of intellectual property rights, rights of privacy or publicity rights, any claims relating to publication of defamatory, pornographic, obscene or offensive material, or any claims relating to the completeness, @@ -518,19 +564,20 @@ Services (hereinafter “External Services”).

      JamKazam does not have or maintain any control over External Services, and is not and cannot be responsible for their content, operation or use. By linking or otherwise providing access to any External Services, JamKazam does not give - any representation, warranty or endorsement, express or implied, with respect to the legality, accuracy, quality or + any representation, warranty or endorsement, express or implied, with respect to the legality, accuracy, quality, security or authenticity of content, information or services provided by such External Services.

      -

      External Services may have their own Terms of Service and/or privacy policy, and may have different practices and +

      External Services may have their own Terms of use or Service and/or privacy policy, and may have different practices and requirements to those operated by JamKazam with respect to the Platform. You are solely responsible for reviewing any - Terms of Service, privacy policy or other terms governing your use of these External Services, which you use at your + such terms of use/service, privacy policy or other terms governing your use of these External Services, which you use at your own risk. You are advised to make reasonable inquiries and investigations before entering into any transaction, financial or otherwise, and whether online or offline, with any third party related to any External Services.

      You are solely responsible for taking the precautions necessary to protect yourself from fraud when using External Services, and to protect your computer systems from viruses, worms, Trojan horses, and other harmful or destructive - content and material that may be included on or may emanate from any External Services.

      -

      JamKazam disclaims any and all responsibility or liability for any harm resulting from your use of External Services, - and you hereby irrevocably waive any claim against JamKazam with respect to the content or operation of any External - Services.

      + content and material that may be included on or may emanate from any External Services. JamKazam makes no representations or warranties + about whether External Services are free of viruses or other forms of data corruption.

      +

      JamKazam disclaims any and all responsibility or liability for any harm or liability resulting from your use of External Services, + and you hereby irrevocably waive any claim against JamKazam with respect to your use of any External + Services.

      Blocking and Removal of Content

      Notwithstanding the fact that JamKazam has no legal obligation to monitor the Content on the Platform, JamKazam @@ -550,7 +597,7 @@ that any of Your Content infringes the copyright or other rights of such third party, or if we believe that your behavior is inappropriate and violates our Terms, we will send you a written warning to this effect. Any user that receives one or more of these warnings is liable to have their access to the Platform terminated - forthwith.

      + in perpetuity.

      We will also suspend or terminate your account without warning if ordered to do so by a court, and/or in other appropriate circumstances, as determined by JamKazam at its discretion.

      Please note we do not offer refunds to Premium Account holders or JamTracks license purchases for those whose @@ -558,17 +605,26 @@

      Disclaimer

      THE PLATFORM, INCLUDING, WITHOUT LIMITATION, THE WEBSITE, THE APPS AND ALL CONTENT AND SERVICES ACCESSED THROUGH OR - VIA THE WEBSITE, THE APPS OR OTHERWISE, ARE PROVIDED “AS IS”, “AS AVAILABLE”, AND “WITH ALL FAULTS”.

      + VIA THE WEBSITE, THE APPS OR OTHERWISE, ARE PROVIDED “AS IS”, “AS AVAILABLE”, AND “WITH ALL FAULTS” WITH NO COMMITMENT TO ANY FUTURE FUNCTIONALITY OR + FEATURES.

      WHILE JAMKAZAM USES COMMERCIALLY REASONABLE EFFORTS TO CORRECT ANY ERRORS OR OMISSIONS IN THE PLATFORM AS SOON AS PRACTICABLE ONCE THEY HAVE BEEN BROUGHT TO OUR ATTENTION, JAMKAZAM MAKES NO PROMISES, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF ANY KIND WHATSOEVER (EXPRESS OR IMPLIED) REGARDING THE WEBSITE, THE APPS, THE SERVICES OR ANY PART OR PARTS THEREOF, ANY CONTENT, OR ANY LINKED SERVICES OR OTHER EXTERNAL SERVICES. JAMKAZAM DOES NOT WARRANT THAT YOUR USE - OF THE PLATFORM WILL BE UNINTERRUPTED, TIMELY, SECURE OR ERROR-FREE, THAT DEFECTS WILL BE CORRECTED, OR THAT THE + OF THE PLATFORM WILL BE UNINTERRUPTED, AVAILABLE AT + ALL TIMES, TIMELY, SECURE OR ERROR-FREE, THAT DEFECTS WILL BE CORRECTED, OR THAT THE PLATFORM OR ANY PART OR PARTS THEREOF, THE CONTENT, OR THE SERVERS ON WHICH THE PLATFORM OPERATES ARE OR WILL BE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. JAMKAZAM DOES NOT WARRANT THAT ANY TRANSMISSION OF CONTENT UPLOADED TO THE - PLATFORM WILL BE SECURE OR THAT ANY ELEMENTS OF THE PLATFORM DESIGNED TO PREVENT UNAUTHORISED ACCESS, SHARING OR + PLATFORM WILL BE ACCURATE OR SECURE OR THAT ANY ELEMENTS OF THE PLATFORM DESIGNED TO PREVENT UNAUTHORIZED ACCESS, SHARING OR DOWNLOAD OF CONTENT WILL BE EFFECTIVE IN ANY AND ALL CASES, AND DOES NOT WARRANT THAT YOUR USE OF THE PLATFORM IS - LAWFUL IN ANY PARTICULAR JURISDICTION.

      + LAWFUL IN ANY PARTICULAR JURISDICTION. YOUR SOLE REMEDY IN THE EVENT OF ANY + DEFICIENCY, ERROR, OR INACCURACY OF THE PLATFORM SHALL BE TO + REQUEST THAT JAMKAZAM CORRECT THE MATTER OR, IF JAMKAZAM FAILS TO + DO SO, TO DISCONTINUE YOUR USE OF THE PLATFORM. ANY CONTENT + DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE + PLATFORM IS DOWNLOADED AT YOUR OWN RISK AND YOU WILL BE SOLELY + RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER OR DEVICE, OR FOR LOSS + OF DATA THAT RESULTS FROM SUCH DOWNLOAD.

      JAMKAZAM AND ITS SUBSIDIARIES, AFFILIATES, SUCCESSORS, AND ASSIGNS, AND THEIR RESPECTIVE EMPLOYEES, AGENTS, DIRECTORS, OFFICERS AND SHAREHOLDERS, SPECIFICALLY DISCLAIM ALL OF THE FOREGOING WARRANTIES AND ANY OTHER WARRANTIES NOT EXPRESSLY SET OUT HEREIN TO THE FULLEST EXTENT PERMITTED BY LAW, INCLUDING WITHOUT LIMITATION ANY EXPRESS OR @@ -584,23 +640,25 @@

      TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL JAMKAZAM OR ITS SUPPLIERS OR LICENSORS BE LIABLE FOR PERSONAL - INJURY, OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER, INCLUDING, WITHOUT LIMITATION, + INJURY, OR ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES WHATSOEVER, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, LOSS OF DATA, BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE THE PLATFORM, HOWEVER CAUSED, REGARDLESS OF THE THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF JAMKAZAM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. IN NO EVENT WILL JAMKAZAM’S TOTAL LIABILITY TO YOU FOR ALL DAMAGES (OTHER - THAN AS MAY BE REQUIRED BY APPLICABLE LAW IN CASES INVOLVING PERSONAL INJURY) EXCEED THE AMOUNT OF FIFTY DOLLARS + THAN AS MAY BE REQUIRED OTHERWISE BY APPLICABLE LAW IN CASES INVOLVING PERSONAL INJURY) EXCEED THE AMOUNT OF FIFTY DOLLARS ($50.00). THE FOREGOING LIMITATIONS WILL APPLY EVEN IF THE ABOVE STATED REMEDY FAILS OF ITS ESSENTIAL PURPOSE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATION OF CERTAIN TYPES OF DAMAGES OR LIABILITIES, SO THE ABOVE EXCLUSION AND LIMITATIONS MAY NOT APPLY TO YOU, BUT IN SUCH A CASE THE FOREGOING WILL BE APPLIED TO THE GREATEST EXTENT ENFORCEABLE UNDER APPLICABLE LAW.

      Indemnification

      -

      You agree to indemnify and hold JamKazam, and its officers, directors, employees, agents, successors, +

      You agree to indemnify, defend and hold JamKazam, and its officers, directors, employees, agents, representatives, licensors, successors, and assigns harmless from and against any claims, liabilities, damages, losses, and expenses, including, - without limitation, reasonable legal and accounting fees, arising out of or in any way connected to (a) - your access, use, or misuse of the Platform, or Materials, or (b) your violation of these Terms. JamKazam will use + without limitation, reasonable attorneys' and accounting fees, arising out of or in any way connected to (a) + your access, use, or misuse of the Platform, or Materials, (b) your violation of these Terms, or (c) any + infringement or misappropriation of any intellectual property right or other right of any person or + entity by you or any other user of your user account. JamKazam will use reasonable efforts to notify you of any such claim, action or proceeding for which it seeks an indemnification from you upon becoming aware of it, but if JamKazam is unable to communicate with you in a timely manner because of an inactive e-mail address for you, your indemnification obligation will continue notwithstanding JamKazam’s inability @@ -615,7 +673,7 @@ the <%= link_to "Privacy Policy", corp_privacy_path %> and our <%= link_to "Cookies Policy", corp_cookie_policy_path %>.

      Use of JamKazam Widgets

      -

      The Platform includes access to embeddable JamKazam services (“Widgets”) for incorporation into users’ own sites, +

      The Platform may include access to embeddable JamKazam services (“Widgets”) for incorporation into users’ own sites, third party sites or social media profiles, whether or not a Linked Service. This functionality is provided to enable Uploaders to put their Content wherever they wish, and to enable other users of the Platform to share and distribute Content within the parameters set by the Uploader.

      @@ -645,7 +703,14 @@ access to the Platform or any part thereof, temporarily or permanently, and whether in its entirety or with respect to individual territories only. In the case of any temporary or permanent suspension, discontinuation, termination or cessation of access, JamKazam shall use commercially reasonable efforts to notify registered users of such decision in - advance.

      + advance. In + addition, you acknowledge that, while JamKazam has undertaken to provide accurate + information via the Platform, it is not comprehensive, and JamKazam makes no commitment to + update the information at any particular time, and the information on the Platform may be out of + date. Information on the Platform may also be changed at any time without notice. As a result, + the information may not be accurate, up to date or applicable to the circumstances of any + particular case. Any decisions you make based on information contained in the Platform are + solely your responsibility.

      You hereby agree that JamKazam and its subsidiaries, affiliates, successors, assigns, employees, agents, directors, officers and shareholders shall not be liable to you or to any third party for any changes or modifications to the Website, Apps and/or any Services that JamKazam may wish to make from time to time, or for any decision to suspend, @@ -665,22 +730,21 @@ of the changes to your account.

      Termination

      -

      These Terms are effective until terminated by you or JamKazam. Your rights under these Terms will terminate +

      These Terms are effective as to you and your use of the Platform until terminated by you or JamKazam. Your rights under these Terms will terminate automatically without notice from JamKazam if you fail to comply with any term(s) of these Terms - (including by violating any license restriction provided herein). You may terminate these Terms by deleting your - account and ceasing use of the Platform. Upon any termination of these Terms, + (including by violating any license restriction provided herein). You may terminate these Terms (as to you only) by deleting your + account and ceasing use of the Platform. Upon any such termination of these Terms, you must immediately cease all use of the Platform. You will not be able to use the Platform without re-registering. You may not re-register if you are prohibited from re-registering by these Terms.

      -

      If you have a Premium Account and terminate this Agreement before the end of your subscription, +

      If you have a Premium Account and terminate before the end of your subscription, or if your account is otherwise suspended or terminated by JamKazam, we are unable to offer any refund for any unexpired period of your subscription. If you have purchased - JamTracks licenses and terminate this Agreement, we will not offer any refund on your JamTracks purchases.

      -

      If you have a Premium Account and your account is suspended or terminated by JamKazam, then JamKazam is not - obligated to provide you with a refund. If you have purchased JamTracks licenses and your account is suspended - or terminated by JamKazam, then JamKazam is not obligated to provide you with a refund.

      -

      Once your account has been terminated, any and all Content residing in your account, or pertaining to activity from + JamTracks licenses and terminate this these Terms pursuant to this section, + or if your account is suspended or terminated by JamKazam, we will not offer any refund on your JamTracks purchases.

      +

      Once your account has been terminated, Your Content residing in your account, or pertaining to activity from your account will be irretrievably deleted by JamKazam, except to the extent that we are obliged or permitted to retain such content, data or information for a certain period of time in accordance with applicable laws and - regulations and/or to protect our legitimate business interests. You are advised to save or back up any material that + regulations and/or to protect our legitimate business interests (or if we are not required to delete such Content, as described herein, such as + when other users beside you own rights in or have contributed to Your Content). You are advised to save or back up any material that you have uploaded to your account before terminating your account, as JamKazam assumes no liability for any material that is irretrievably deleted following any termination of your account. JamKazam is not able to provide you with any .csv or other similar file of data relating to activity associated with your account, whether before or after @@ -700,9 +764,9 @@ and Applicable Law and Jurisdiction, respectively.

      Assignment to Third Parties

      -

      JamKazam may assign its rights and (where permissible by law) its obligations under this Agreement, in whole or in +

      JamKazam may assign its rights and (where permissible by law) its obligations under these Terms, in whole or in part, to any third party at any time without notice, including without limitation, to any person or entity acquiring - all or substantially all of the assets or business of JamKazam. You may not assign this Agreement or the rights and + all or substantially all of the assets or business of JamKazam. You may not assign these Terms or the rights and duties hereunder, in whole or in part, to any third party without the prior written consent of JamKazam.

      Severability

      @@ -715,7 +779,8 @@  and <%= link_to "Cookies Policy", corp_cookie_policy_path %>, constitute the entire agreement between you and JamKazam with respect to your use of the Platform (other than any use of JamKazam’s APIs which may also be subject to separate API Terms of Service), and supersede any prior agreement between you and JamKazam. Any modifications to this Agreement - must be made in writing.

      + must be made in writing. No waiver by JamKazam of any breach or default + hereunder shall be deemed to be a waiver of any preceding or subsequent breach or default.

      Third Party Rights

      @@ -723,7 +788,7 @@ right to transfer our rights or obligations to a third party as described in the Assignment to Third Parties section.

      -

      Applicable Law and Jurisdiction

      +

      Dispute Resolution

      1. Mandatory Arbitration. Please read this carefully. It affects your rights. YOU AND JAMKAZAM AND EACH OF OUR RESPECTIVE CORPORATE PARENTS, SUBSIDIARIES, AFFILIATES, PREDECESSORS IN INTEREST, @@ -739,18 +804,18 @@ send to the other, by certified mail, a written notice of intent to arbitrate (a “Notice”), or, in the absence of a mailing address provided by you to JamKazam, to you via any other method available to JamKazam, including via e-mail. The Notice to - JamKazam should be addressed to JamKazam, Inc., Attn: Chief Operating Officer, 5813 Lookout Mountain Drive, + JamKazam should be addressed to JamKazam, Inc., Attn: Chief Operating Officer, 3924 Knollwood Drive,, Austin TX 78731 (the “Arbitration Notice Address”). The Notice must (i) describe the nature and basis of the - claim or dispute; and (ii) set forth the specific relief sought (the “Demand”). If you and JamKazam do not - reach an agreement to resolve the claim within 30 days after the Notice is received, you or JamKazam + Demand or dispute; and (ii) set forth the specific relief sought (the “Demand”). If you and JamKazam do not + reach an agreement to resolve the Demand within 30 days after the Notice is received, you or JamKazam may commence an arbitration proceeding as set forth below or file a claim in small claims court. THE ARBITRATION WILL BE ADMINISTERED BY THE AMERICAN ARBITRATION ASSOCIATION (“AAA”) IN ACCORDANCE WITH ITS COMMERCIAL ARBITRATION RULES AND THE SUPPLEMENTARY PROCEDURES FOR CONSUMER RELATED DISPUTES (THE “Rules”), AS MODIFIED BY THIS AGREEMENT. The Rules and AAA forms are available online at www.adr.org. If you are required to pay a filing fee to commence an arbitration against JamKazam, then JamKazam will promptly reimburse you for your confirmed payment of the filing fee upon JamKazam’s receipt of Notice at the Arbitration Notice Address that - you have commenced arbitration along with a receipt evidencing payment of the filing fee, unless your Demand is - equal to or greater than $1,000 or was filed in bad faith, in which case you are solely responsible for the payment + you have commenced arbitration along with a receipt evidencing payment of the filing fee; provided, however, that if your Demand is + equal to or greater than $1,000 or was filed in bad faith, you, not JamKazam, are solely responsible for the payment of the filing fee.
      2. Arbitration Proceeding. The arbitration will be conducted in English. @@ -773,14 +838,14 @@ will be closed to the public and confidential and all records relating thereto will be permanently sealed, except as necessary to obtain court confirmation of the arbitration award. The award of the arbitrator shall be in writing and will include a statement setting forth the reasons for the disposition of any claim. The arbitrator will apply - the laws of the State of Texas in conducting the arbitration. You acknowledge that these terms and your use of the - App evidences a transaction involving interstate commerce. The United States Federal Arbitration Act will govern + the laws of the State of Texas in conducting the arbitration. You acknowledge that these Terms and your use of the + Platform evidences a transaction involving interstate commerce. The United States Federal Arbitration Act will govern the interpretation, enforcement, and proceedings pursuant to the Mandatory Arbitration clause in these Terms.
    7. Equitable Relief. The foregoing provisions of this Dispute Resolution section do not - apply to any claim in which either party seeks equitable relief to protect such party’s copyrights, trademarks, or + apply to any claim in which either party seeks equitable relief to protect such party’s copyrights, trademarks, trade secrets, or patents. You acknowledge that, in the event of a breach of these Terms by JamKazam or any third party, the damage or harm, if any, caused to you will not entitle you to seek injunctive or other equitable relief against JamKazam, and your only remedy will be for monetary damages, subject to the limitations of liability @@ -795,21 +860,22 @@ may recover attorneys’ fees and costs up to $5,000, provided that JamKazam has notified you in writing of the improperly filed claim, and you have failed to promptly withdraw the claim.
    8. Modifications. In the event that JamKazam makes any future change to the - Mandatory Arbitration provision (other than a change to JamKazam’s Arbitration Notice Address), + Mandatory Arbitration provision above (other than a change to JamKazam’s Arbitration Notice Address), you may reject any such change by sending us written notice within thirty (30) days of the change to JamKazam’s Arbitration Notice Address, in which case your account with JamKazam and your license to use - the Service shall terminate immediately, and this Dispute Resolution provision, as in effect immediately + the Platform shall terminate immediately, and this Dispute Resolution provision, as in effect immediately prior to the amendments you reject, will survive the termination of these Terms.
    9. -
    10. Enforceability. If only Section 27.a.iii or the entirety of this Section 27 - is found to be unenforceable, then the entirety of this Section 27 will be null and void and, in such case, - the parties agree that the exclusive jurisdiction and venue described in Section 28 will govern any action +
    11. Enforceability. If the entirety of this Dispute Resolution section + is found to be unenforceable, then the entirety of this section will be null and void and, in such case, + the parties agree that the exclusive jurisdiction and venue described in the "Governing Law" section below will govern any action arising out of or related to these Terms.

    Governing Law

    The laws of the State of Texas, excluding its conflicts of law rules, govern these Terms and your use of the Platform. Your use of the Platform may also be subject to other local, state, national, or international laws. - To the extent that any action relating to any dispute hereunder is permitted to be brought in a court of law, such + To the extent that any action relating to any dispute hereunder is permitted to be brought in a court of law, except as set forth to the contrary in the “Dispute Resolution” + section above, such action shall be subject to the exclusive jurisdiction of the state and federal courts located in Travis County, Texas, and you hereby irrevocably submit to personal jurisdiction in such courts, and waive any defense of inconvenient forum. @@ -823,8 +889,8 @@

    Contact Us

    The services hereunder are offered by JamKazam, Inc., a Delaware corporation and with its main place of business at - 5813 Lookout Mountain Drive, Austin TX 78731. You may contact us by sending correspondence to the foregoing address or + 3924 Knollwood Drive,, Austin TX 78731. You may contact us by sending correspondence to the foregoing address or by emailing us at info@jamkazam.com.


    -

    Last Amended: 24 April 2015

    +

    Last Amended: 30 September 2020

    diff --git a/web/app/views/dialogs/_acceptFriendRequestDialog.html.haml b/web/app/views/dialogs/_acceptFriendRequestDialog.html.haml index 87dcac85f..af742bfc1 100644 --- a/web/app/views/dialogs/_acceptFriendRequestDialog.html.haml +++ b/web/app/views/dialogs/_acceptFriendRequestDialog.html.haml @@ -42,7 +42,7 @@ Or, you can also go straight to the %a{href: "/client#/createSession", class: 'create-session-already-friends'} create session page and click - %b QUICK START SOLO + %b QUICK START PRIVATE to create a private session that only your friends can join! %br{clear:'all'} %br{clear:'all'} diff --git a/web/config/application.rb b/web/config/application.rb index d93dbc438..b8b87255d 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -456,7 +456,7 @@ if defined?(Bundler) config.end_of_wait_window_forgiveness_minutes = 1 config.olark_enabled = false config.jamclass_enabled = false - config.musician_count = '75,000+' + config.musician_count = '200,000+' config.jamblaster_menu = false # Applications created before Rails 4.1 uses Marshal to serialize cookie values into the signed and encrypted cookie jars. # If you want to use the new JSON-based format in your application, you can add an initializer file with the following content: @@ -478,5 +478,10 @@ if defined?(Bundler) config.rating_dialog_min_num = 1 config.gcp_stats_host = "https://us-central1-tough-craft-276813.cloudfunctions.net" + + config.root_redirect_on = true + config.root_redirect_subdomain = '' + config.root_redirect_path = '/' + end end diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb index 9f2a103b1..f31401eba 100644 --- a/web/config/environments/development.rb +++ b/web/config/environments/development.rb @@ -111,4 +111,5 @@ SampleApp::Application.configure do config.rating_dialog_min_time = 1 config.rating_dialog_min_num = 1 + config.root_redirect_on = false end diff --git a/web/config/routes.rb b/web/config/routes.rb index 96b950479..610fc1fee 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -8,7 +8,14 @@ Rails.application.routes.draw do resources :users resources :sessions, only: [:new, :create, :destroy] - root to: 'users#home' + if Rails.application.config.root_redirect_on + root to: redirect(subdomain: Rails.application.config.root_redirect_subdomain, path: Rails.application.config.root_redirect_path) # => foo.example.com/bar + else + root to: 'users#home' + end + + + # signup, and signup completed, related pages get '/signup', to: 'users#new' diff --git a/web/lib/music_session_manager.rb b/web/lib/music_session_manager.rb index ff62931d9..cc04f7a72 100644 --- a/web/lib/music_session_manager.rb +++ b/web/lib/music_session_manager.rb @@ -20,6 +20,8 @@ class MusicSessionManager < BaseManager active_music_session = ActiveMusicSession.new active_music_session.id = music_session.id # copy the .id from music_session to active_music_session active_music_session.creator = user + active_music_session.school_id = user.school_id + active_music_session.is_platform_instructor = user.is_platform_instructor if fan_access # create an icecast mount since regular users can listen in to the broadcast @@ -96,12 +98,15 @@ class MusicSessionManager < BaseManager def participant_create(user, music_session_id, client_id, as_musician, tracks, audio_latency) connection = nil music_session = nil + active_music_session = nil + send_track_changed = false ActiveRecord::Base.transaction do active_music_session = ActiveMusicSession.find(music_session_id) active_music_session.with_lock do # VRFS-1297 active_music_session.tick_track_changes + send_track_changed = true connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency) if connection.errors.any? @@ -111,6 +116,9 @@ class MusicSessionManager < BaseManager end end + if send_track_changed + Notification.send_tracks_changed(active_music_session) + end unless connection.errors.any? user.update_progression_field(:first_music_session_at) @@ -141,14 +149,20 @@ class MusicSessionManager < BaseManager recordingId = nil + tracks_changed = false active_music_session.with_lock do # VRFS-1297 ConnectionManager.new.leave_music_session(user, connection, active_music_session) do active_music_session.tick_track_changes + tracks_changed = true recording = active_music_session.stop_recording # stop any ongoing recording, if there is one recordingId = recording.id unless recording.nil? end end + if tracks_changed + Notification.send_tracks_changed(active_music_session) + end + Notification.send_session_depart(active_music_session, connection.client_id, user, recordingId) end diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb index 01d6cb02e..233b2c007 100644 --- a/web/lib/user_manager.rb +++ b/web/lib/user_manager.rb @@ -47,6 +47,10 @@ class UserManager < BaseManager test_drive_package = options[:test_drive_package] under_13 = options[:under_13] timezone = options[:timezone] + platform_instructor = options[:platform_instructor] + license_start = options[:license_start] + license_end = options[:license_end] + import_source = options[:import_source] recaptcha_failed = false unless options[:skip_recaptcha] # allow callers to opt-of recaptcha @@ -68,7 +72,7 @@ class UserManager < BaseManager unless location.nil? loc[:city] = location[:city] loc[:state] = location[:state] - loc[:country] = location[:country] + loc[:country] = location[:country] end # sends email to email account for confirmation @@ -104,7 +108,11 @@ class UserManager < BaseManager origin: origin, test_drive_package: test_drive_package, under_13: under_13, - timezone: timezone) + timezone: timezone, + platform_instructor: platform_instructor, + license_start: license_start, + license_end: license_end, + import_source: import_source) user end diff --git a/websocket-gateway/lib/jam_websockets/router.rb b/websocket-gateway/lib/jam_websockets/router.rb index 3404e67fc..062050a6d 100644 --- a/websocket-gateway/lib/jam_websockets/router.rb +++ b/websocket-gateway/lib/jam_websockets/router.rb @@ -252,8 +252,10 @@ module JamWebsockets @client_lookup.each do |client_id, client_context| if @chat_blast || client_context.active client = client_context.client + user = client_context.user - if client + # disable global chat for schoolers for now + if client && user && user.school_id.nil? EM.schedule do #@log.debug "sending client-directed down websocket to #{client_id}" send_to_client(client, msg) @@ -1360,8 +1362,19 @@ module JamWebsockets # it's possible that a client will not be represented in the database anymore, due to hard to trace/guess scenario # usually involve reconnects. Double-check that all clients in memory are actually in the database. if not, delete them from memory - @stored_ars = Ars.active_arses(true) - @stored_ars_beta = Ars.active_arses(false) + stored_ars_raw = Ars.active_arses(true) + stored_ars_beta_raw = Ars.active_arses(false) + + stored_ars = [] + stored_ars_beta = [] + stored_ars_raw.each do |ars| + stored_ars << @message_factory.ars_body(ars) + end + stored_ars_beta_raw.each do |ars| + stored_ars_beta << @message_factory.ars_body(ars) + end + @stored_ars = stored_ars + @stored_ars_beta = stored_ars_beta if @client_lookup.length == 0 return