* VRFS-3912 - apis for jamblaster pairing

This commit is contained in:
Seth Call 2016-02-03 10:56:14 -06:00
parent 48be48caf5
commit 599d26f883
21 changed files with 525 additions and 1 deletions

View File

@ -0,0 +1,16 @@
ActiveAdmin.register JamRuby::Jamblaster, :as => 'Jamblaster' do
menu :label => 'JamBlasters', :parent => 'JamBlaster'
form do |f|
f.inputs 'New JamBlaster' do
f.input :user, required: true, collection: User.all, include_blank: false
f.input :serial_no, required: true
f.input :client_id, required: false
f.input :vtoken, required: false
f.input :users, required: true, collection: User.all, include_blank: false
end
f.actions
end
end

View File

@ -328,4 +328,5 @@ populate_subjects.sql
reviews.sql
download_tracker_fingerprints.sql
connection_active.sql
chat_channel.sql
chat_channel.sql
jamblaster.sql

28
db/up/jamblaster.sql Normal file
View File

@ -0,0 +1,28 @@
CREATE TABLE jamblasters (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE SET NULL,
serial_no VARCHAR(1000) UNIQUE,
vtoken VARCHAR(1000) UNIQUE,
client_id VARCHAR(64) UNIQUE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE jamblasters_users (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
jamblaster_id VARCHAR(64) NOT NULL REFERENCES jamblasters(id) ON DELETE CASCADE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE jamblaster_pairing_requests (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
jamblaster_id VARCHAR(64) NOT NULL REFERENCES jamblasters(id) ON DELETE CASCADE,
jamblaster_client_id VARCHAR(64) NOT NULL,
sibling_client_id VARCHAR(64) NOT NULL,
sibling_key VARCHAR(1000) NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);

View File

@ -102,6 +102,9 @@ message ClientMessage {
RESTART_APPLICATION = 403;
STOP_APPLICATION = 404;
// jamblaster messages
PAIR_ATTEMPT = 500;
SERVER_BAD_STATE_RECOVERED = 900;
SERVER_GENERIC_ERROR = 1000;
@ -217,6 +220,9 @@ message ClientMessage {
optional RestartApplication restart_application = 403;
optional StopApplication stop_application = 404;
// JamBlaster messages
optional PairAttempt pair_attempt = 500;
// Server-to-Client special messages
optional ServerBadStateRecovered server_bad_state_recovered = 900;
@ -750,6 +756,11 @@ message StopApplication {
}
message PairAttempt {
optional string scid = 1;
optional string vtoken = 2;
}
// route_to: client
// this should follow a ServerBadStateError in the case that the
// websocket gateway recovers from whatever ailed it

View File

@ -264,6 +264,9 @@ require "jam_ruby/models/gift_card"
require "jam_ruby/models/gift_card_purchase"
require "jam_ruby/models/gift_card_type"
require "jam_ruby/models/jam_track_session"
require "jam_ruby/models/jamblaster"
require "jam_ruby/models/jamblaster_user"
require "jam_ruby/models/jamblaster_pairing_request"
include Jampb

View File

@ -921,6 +921,18 @@ module JamRuby
)
end
def pair_attempt(jbid, scid, vtoken)
pair_attempt = Jampb::PairAttempt.new(
:scid => scid,
:vtoken => vtoken
)
Jampb::ClientMessage.new(
:type => ClientMessage::Type::PAIR_ATTEMPT,
:route_to => CLIENT_TARGET_PREFIX + jbid,
:pair_attempt => pair_attempt
)
end
# create a musician fresh session message
def musician_session_fresh(session_id, user_id, username, photo_url)
fresh = Jampb::MusicianSessionFresh.new(

View File

@ -0,0 +1,39 @@
module JamRuby
class Jamblaster < ActiveRecord::Base
attr_accessible :user_id, :serial_no, :client_id, :vtoken, :user_ids, as: :admin
belongs_to :user, class_name: 'JamRuby::User'
has_many :jamblasters_users, class_name: "JamRuby::JamblasterUser"
has_many :users, class_name: 'JamRuby::User', through: :jamblasters_users
has_many :jamblaster_pairing_requests, class_name: "JamRuby::JamblasterPairingRequest", foreign_key: :jamblaster_id
validates :user, presence: true
validates :serial_no, uniqueness: true
validates :vtoken, uniqueness: true
validates :client_id, uniqueness: true
before_save :sanitize_active_admin
def sanitize_active_admin
self.vtoken = nil if self.vtoken == ''
self.client_id = nil if self.client_id == ''
end
class << self
@@mq_router = MQRouter.new
@@message_factory = MessageFactory.new
def send_pair_attempt(jbid, scid, vtoken)
msg = @@message_factory.pair_attempt(
jbid, scid, vtoken
)
@@mq_router.publish_to_client(jbid, msg, {:client_id => scid})
end
end
end
end

View File

@ -0,0 +1,14 @@
module JamRuby
class JamblasterPairingRequest < ActiveRecord::Base
belongs_to :user, class_name: 'JamRuby::User'
belongs_to :jamblaster, class_name: 'JamRuby::Jamblaster', foreign_key: :jamblaster_id
validates :user, presence: true
validates :jamblaster, presence: true
validates :jamblaster_client_id, presence: true
validates :sibling_client_id, presence: true
validates :sibling_key, presence: true
end
end

View File

@ -0,0 +1,11 @@
module JamRuby
class JamblasterUser < ActiveRecord::Base
self.table_name = "jamblasters_users"
belongs_to :jamblaster, class_name: "JamRuby::Jamblaster"
belongs_to :user, class_name: "JamRuby::User"
validates :jamblaster, presence:true
validates :user, presence: true
end
end

View File

@ -191,6 +191,9 @@ module JamRuby
has_many :jam_track_session, :class_name => "JamRuby::JamTrackSession"
has_many :jamblasters_users, class_name: "JamRuby::JamblasterUser"
has_many :jamblasters, class_name: 'JamRuby::Jamblaster', through: :jamblasters_users
before_save :default_anonymous_names
before_save :create_remember_token, :if => :should_validate_password?
before_save :stringify_avatar_info, :if => :updating_avatar

View File

@ -888,4 +888,23 @@ FactoryGirl.define do
association :user, factory: :user
end
factory :jamblaster, class: 'JamRuby::Jamblaster' do
association :user, factory: :user
sequence(:serial_no ) { |n| "serial_no#{n}" }
sequence(:vtoken ) { |n| "vtoken#{n}" }
sequence(:client_id ) { |n| "client_id#{n}" }
end
factory :jamblaster_pairing_request, class: 'JamRuby::JamblasterPairingRequest' do
association :user, factory: :user
association :jamblaster, factory: :jamblaster
sequence(:jamblaster_client_id ) { |n| "jamblaster_client_id#{n}" }
sequence(:sibling_client_id ) { |n| "sibling_client_id#{n}" }
sequence(:sibling_key ) { |n| "sibling_key#{n}" }
end
end

View File

@ -0,0 +1,17 @@
require 'spec_helper'
describe Jamblaster do
let(:jamblaster) {FactoryGirl.create(:jamblaster)}
let(:user) {FactoryGirl.create(:user)}
it "can be created" do
FactoryGirl.create(:jamblaster)
end
it "can associate to users" do
jamblaster.users.should eq([])
user.jamblasters.should eq([])
end
end

View File

@ -0,0 +1,100 @@
class ApiJamblastersController < ApiController
before_filter :api_signed_in_user, except: [:login, :store_token]
respond_to :json
def get_tokens
@jamblasters = current_user.jamblasters
end
def start_pairing
jamblaster = Jamblaster.find_by_client_id(params[:jbid])
if jamblaster && !current_user.jamblasters.include?(jamblaster)
render :json => {reason: "jamblaster_access", message: "current user does not have access to jamblaster #{jamblaster.id}"}, status: 403
return
end
@pairing = JamblasterPairingRequest.new
@pairing.user = current_user
@pairing.jamblaster_client_id = params[:jbid]
@pairing.jamblaster = jamblaster
@pairing.sibling_client_id = params[:scid]
@pairing.sibling_key = params[:key]
if !@pairing.save
respond_with_model(@pairing)
else
end
end
def login
scid = params[:scid]
jbid = params[:jbid]
key = params[:key]
serial_no = params[:serial_no]
pairing_request = JamblasterPairingRequest.where(jamblaster_client_id: jbid).where(sibling_client_id: scid).where(sibling_key: key).first
jamblaster = Jamblaster.find_by_serial_no(serial_no)
if jamblaster.nil?
render :json => { :message => 'No jamblaster found with serial_no ' + serial_no, reason: "serial_no" }, :status => 404
return
end
if pairing_request.nil?
render :json => { :message => "No pairing request found with jbid=#{jbid} && sibling_client_id=#{scid} && sibling_key=#{key}", reason: "no_pairing_request" }, :status => 404
return
end
render :json => {remember_token: pairing_request.user.remember_token}, :status => 200
end
def store_token
vtoken = params[:vtoken]
scid = params[:scid]
jbid = params[:jbid]
key = params[:key]
pairing_request = JamblasterPairingRequest.where(jamblaster_client_id: jbid).where(sibling_client_id: scid).where(sibling_key: key).first
if pairing_request.nil?
render :json => { :message => "No pairing request found with jbid=#{jbid} && sibling_client_id=#{scid} && sibling_key=#{key}", reason: "no_pairing_request" }, :status => 404
return
end
if vtoken.blank?
render :json => { :errors => { vtoken: ['is empty'] } }, :status => 422
return
end
@jamblaster = pairing_request.jamblaster
@jamblaster.vtoken = vtoken
if !@jamblaster.save
respond_with_model(@jamblaster)
else
end
end
def pair
vtoken = params[:vtoken]
scid = params[:scid]
jbid = params[:jbid]
jamblaster = Jamblaster.find_by_vtoken(vtoken)
if jamblaster.nil?
render :json => {reason: "no_vtoken", message: "No jamblaster found with vtoken:#{vtoken}" }, status: 404
return
end
if !current_user.jamblasters.include?(jamblaster)
render :json => {reason: "jamblaster_access", message: "current user does not have access to jamblaster #{jamblaster.id} with vtoken #{vtoken}"}, status: 403
return
end
Jamblaster.send_pair_attempt(jbid, scid, vtoken)
@jamblaster = jamblaster
end
end

View File

@ -0,0 +1,4 @@
object @jamblasters
attributes :id, :serial_no, :client_id, :vtoken

View File

View File

@ -0,0 +1,3 @@
object @jamblaster
attributes :id

View File

@ -0,0 +1,4 @@
object @pairing
attributes :id

View File

@ -0,0 +1,3 @@
object @jamblaster
attributes :id

View File

@ -675,5 +675,11 @@ SampleApp::Application.routes.draw do
match '/links/jamkazam' => 'api_links#jamkazam_general_index'
match '/links/sessions' => 'api_links#session_index'
match '/links/recordings' => 'api_links#recording_index'
match 'jamblasters/pairing/tokens' => 'api_jamblasters#get_tokens', :via => :get
match 'jamblasters/pairing/start' => 'api_jamblasters#start_pairing', :via => :post
match 'jamblasters/pairing/login' => 'api_jamblasters#login', :via => :post
match 'jamblasters/pairing/store' => 'api_jamblasters#store_token', :via => :post
match 'jamblasters/pairing/pair' => 'api_jamblasters#pair', :via => :post
end
end

View File

@ -0,0 +1,211 @@
require 'spec_helper'
describe ApiJamblastersController do
render_views
let(:user) {FactoryGirl.create(:user)}
let(:jamblaster) { FactoryGirl.create(:jamblaster, user: user) }
before(:each) do
JamblasterUser.delete_all
JamblasterPairingRequest.delete_all
Jamblaster.delete_all
end
describe "get_tokens" do
before(:each) {
controller.current_user = user
}
it "works" do
get :get_tokens, {:format=>'json' }
response.status.should == 200
json = JSON.parse(response.body)
json.length.should eq(0)
# associate Jamblaster
jamblaster = FactoryGirl.create(:jamblaster, user: user)
user.jamblasters << jamblaster
user.save!
get :get_tokens, {:format=>'json' }
response.status.should == 200
json = JSON.parse(response.body)
json.length.should eq(1)
end
end
describe "start_pairing" do
before(:each) do
controller.current_user = user
user.jamblasters << jamblaster
user.save!
end
it "works" do
post :start_pairing, {:format=>'json', jbid: jamblaster.client_id, scid: 'sibling_id', key: 'sibling_key'}
json = JSON.parse(response.body)
response.status.should == 200
request = JamblasterPairingRequest.where(jamblaster_id: jamblaster.id).first
request.should_not be_nil
request.user.should eql(user)
request.sibling_key.should eq 'sibling_key'
request.sibling_client_id.should eq 'sibling_id'
end
it "returns 422 if bogus jamblaster" do
post :start_pairing, {:format=>'json', jbid: 'nada', scid: 'sibling_id', key: 'sibling_key'}
json = JSON.parse(response.body)
response.status.should == 422
json = JSON.parse(response.body)
end
it "returns 422 if restart pairing" do
end
end
describe "login" do
before(:each) do
controller.current_user = user
user.jamblasters << jamblaster
user.save!
end
it "works" do
post :start_pairing, {:format=>'json', jbid: jamblaster.client_id, scid: 'sibling_id2', key: 'sibling_key2'}
response.status.should == 200
request = JamblasterPairingRequest.where(jamblaster_client_id: jamblaster.client_id, sibling_key: 'sibling_key2', sibling_client_id: 'sibling_id2').first
request.should_not be_nil
request.user.should eql(user)
request.sibling_key.should eq 'sibling_key2'
request.sibling_client_id.should eq 'sibling_id2'
request.jamblaster_client_id.should eq jamblaster.client_id
post :login, {:format=>'json', jbid: jamblaster.client_id, serial_no: jamblaster.serial_no, scid: 'sibling_id2', key: 'sibling_key2'}
json = JSON.parse(response.body)
response.status.should == 200
json['remember_token'].should eq(user.remember_token)
end
end
describe "store_token" do
before(:each) do
controller.current_user = user
user.jamblasters << jamblaster
user.save!
end
it "works" do
post :start_pairing, {:format=>'json', jbid: jamblaster.client_id, scid: 'sibling_id3', key: 'sibling_key3'}
response.status.should == 200
request = JamblasterPairingRequest.where(jamblaster_client_id: jamblaster.client_id, sibling_key: 'sibling_key3', sibling_client_id: 'sibling_id3').first
request.should_not be_nil
request.user.should eql(user)
request.sibling_key.should eq 'sibling_key3'
request.sibling_client_id.should eq 'sibling_id3'
request.jamblaster_client_id.should eq jamblaster.client_id
post :login, {:format=>'json', jbid: jamblaster.client_id, serial_no: jamblaster.serial_no, scid: 'sibling_id3', key: 'sibling_key3'}
json = JSON.parse(response.body)
response.status.should == 200
json['remember_token'].should eq(user.remember_token)
post :store_token, {:format => 'json', vtoken: 'vtoken1', scid: 'sibling_id3', jbid: jamblaster.client_id, key: 'sibling_key3'}
json = JSON.parse(response.body)
response.status.should == 200
json['id'].should eq(jamblaster.id)
end
end
describe "pair" do
before(:each) do
controller.current_user = user
user.jamblasters << jamblaster
user.save!
end
it "works" do
post :start_pairing, {:format=>'json', jbid: jamblaster.client_id, scid: 'sibling_id4', key: 'sibling_key4'}
response.status.should == 200
request = JamblasterPairingRequest.where(jamblaster_client_id: jamblaster.client_id, sibling_key: 'sibling_key4', sibling_client_id: 'sibling_id4').first
request.should_not be_nil
request.user.should eql(user)
request.sibling_key.should eq 'sibling_key4'
request.sibling_client_id.should eq 'sibling_id4'
request.jamblaster_client_id.should eq jamblaster.client_id
post :login, {:format=>'json', jbid: jamblaster.client_id, serial_no: jamblaster.serial_no, scid: 'sibling_id4', key: 'sibling_key4'}
json = JSON.parse(response.body)
response.status.should == 200
json['remember_token'].should eq(user.remember_token)
post :store_token, {:format => 'json', vtoken: 'vtoken2', scid: 'sibling_id4', jbid: jamblaster.client_id, key: 'sibling_key4'}
json = JSON.parse(response.body)
response.status.should == 200
json['id'].should eq(jamblaster.id)
get :get_tokens, {:format=>'json' }
response.status.should == 200
json = JSON.parse(response.body)
json.length.should eq(1)
vtoken = json[0]["vtoken"]
vtoken.should eq("vtoken2")
post :pair, {:format => 'json', vtoken: 'vtoken2', scid: 'sibling_id4', jbid: jamblaster.client_id}
response.status.should == 200
json = JSON.parse(response.body)
json["id"].should eq jamblaster.id
end
end
describe "logged in" do
before(:each) do
controller.current_user = user
end
it "get_tokens" do
get :get_tokens, {:format=>'json' }
response.status.should == 200
end
it "start_pairing" do
post :start_pairing, {:format=>'json'}
response.status.should == 422
end
it "pair" do
post :pair, {:format=>'json'}
response.status.should == 404
end
end
describe "not logged in" do
before(:each) do
controller.current_user = nil
end
it "get_tokens" do
get :get_tokens, {:format=>'json'}
response.status.should == 403
end
it "start_pairing" do
post :start_pairing, {:format=>'json'}
response.status.should == 403
end
it "pair" do
post :pair, {:format=>'json'}
response.status.should == 403
end
end
end

View File

@ -856,4 +856,23 @@ FactoryGirl.define do
sequence(:code) {|n| n.to_s}
card_type GiftCard::JAM_TRACKS_5
end
factory :jamblaster, class: 'JamRuby::Jamblaster' do
association :user, factory: :user
sequence(:serial_no ) { |n| "serial_no#{n}" }
sequence(:vtoken ) { |n| "vtoken#{n}" }
sequence(:client_id ) { |n| "client_id#{n}" }
end
factory :jamblaster_pairing_request, class: 'JamRuby::JamblasterPairingRequest' do
association :user, factory: :user
association :jamblaster, factory: :jamblaster
sequence(:jamblaster_client_id ) { |n| "jamblaster_client_id#{n}" }
sequence(:sibling_client_id ) { |n| "sibling_client_id#{n}" }
sequence(:sibling_key ) { |n| "sibling_key#{n}" }
end
end