diff --git a/.gitignore b/.gitignore
index 32af8a97..f9bf6839 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ vendor/.bundle
!/log/.keep
!/tmp/.keep
.env
+coverage
# Ignore Byebug command history file.
.byebug_history
diff --git a/Gemfile b/Gemfile
index 6cf5b618..75554816 100644
--- a/Gemfile
+++ b/Gemfile
@@ -49,6 +49,11 @@ group :development do
gem 'spring-watcher-listen', '~> 2.0.0'
end
+group :test do
+ gem 'mocha'
+ gem 'simplecov', :require => false
+end
+
group :production do
# For more condensed logging
gem "lograge"
diff --git a/Gemfile.lock b/Gemfile.lock
index 0a422138..999bd378 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -56,6 +56,7 @@ GEM
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
+ docile (1.1.5)
dotenv (2.1.1)
dotenv-rails (2.1.1)
dotenv (= 2.1.1)
@@ -99,12 +100,15 @@ GEM
nokogiri (>= 1.5.9)
mail (2.6.4)
mime-types (>= 1.16, < 4)
+ metaclass (0.0.4)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
minitest (5.9.1)
+ mocha (1.2.1)
+ metaclass (~> 0.0.1)
multi_json (1.12.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
@@ -177,6 +181,11 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
+ simplecov (0.13.0)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.0)
spring (2.0.0)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
@@ -228,6 +237,7 @@ DEPENDENCIES
jquery-ui-rails
listen (~> 3.0.5)
lograge
+ mocha
omniauth (= 1.3.1)
omniauth-google-oauth2 (= 0.4.1)
omniauth-twitter (= 1.2.1)
@@ -236,6 +246,7 @@ DEPENDENCIES
rails (~> 5.0.0, >= 5.0.0.1)
rails-timeago (~> 2.0)
sass-rails (~> 5.0)
+ simplecov
spring
spring-watcher-listen (~> 2.0.0)
sqlite3
diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb
index 6f8735c4..e1d67eaf 100644
--- a/app/controllers/bbb_controller.rb
+++ b/app/controllers/bbb_controller.rb
@@ -21,7 +21,6 @@ class BbbController < ApplicationController
before_action :load_and_authorize_room_owner!, only: [:end]
skip_before_action :verify_authenticity_token, only: :callback
- before_action :validate_checksum, only: :callback
# GET /:resource/:id/join
# GET /:resource/:room_id/:id/join
@@ -104,9 +103,13 @@ class BbbController < ApplicationController
end
end
- # POST /:resource/:id/callback
+ # POST /:resource/:room_id/:id/callback
# Endpoint for webhook calls from BigBlueButton
def callback
+ # respond with 200 anyway so BigBlueButton knows the hook call was ok
+ # but abort execution
+ head(:ok) && return unless validate_checksum
+
begin
data = JSON.parse(read_body(request))
treat_callback_event(data["event"])
@@ -114,11 +117,10 @@ class BbbController < ApplicationController
logger.error "Error parsing webhook data. Data: #{data}, exception: #{e.inspect}"
# respond with 200 anyway so BigBlueButton knows the hook call was ok
- render head(:ok)
+ head(:ok) && return
end
end
- # DELETE /rooms/:id/end
# DELETE /rooms/:room_id/:id/end
def end
load_and_authorize_room_owner!
@@ -130,7 +132,7 @@ class BbbController < ApplicationController
render_bbb_response bbb_res
end
- # GET /rooms/:id/recordings
+ # GET /rooms/:room_id/recordings
# GET /rooms/:room_id/:id/recordings
def recordings
load_room!
@@ -144,7 +146,7 @@ class BbbController < ApplicationController
render_bbb_response bbb_res, bbb_res[:recordings]
end
- # PATCH /rooms/:id/recordings/:record_id
+ # PATCH /rooms/:room_id/recordings/:record_id
# PATCH /rooms/:room_id/:id/recordings/:record_id
def update_recordings
published = params[:published] == 'true'
@@ -156,7 +158,7 @@ class BbbController < ApplicationController
render_bbb_response bbb_res
end
- # DELETE /rooms/:id/recordings/:record_id
+ # DELETE /rooms/:room_id/recordings/:record_id
# DELETE /rooms/:room_id/:id/recordings/:record_id
def delete_recordings
recording = bbb_get_recordings({recordID: params[:record_id]})[:recordings].first
@@ -259,10 +261,7 @@ class BbbController < ApplicationController
if calculated_checksum != checksum
logger.error "Checksum did not match. Calculated: #{calculated_checksum}, received: #{checksum}"
-
- # respond with 200 anyway so BigBlueButton knows the hook call was ok
- # but abort execution
- render head(:ok) && return
+ false
end
end
diff --git a/app/controllers/landing_controller.rb b/app/controllers/landing_controller.rb
index 93062bc2..b02ed8aa 100644
--- a/app/controllers/landing_controller.rb
+++ b/app/controllers/landing_controller.rb
@@ -48,10 +48,6 @@ class LandingController < ApplicationController
render layout: false
end
- def auth_failure
- redirect_to '/'
- end
-
def admin?
@user && @user == current_user
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index cac3140b..01f1f979 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -34,4 +34,8 @@ class SessionsController < ApplicationController
end
redirect_to root_path
end
+
+ def auth_failure
+ redirect_to '/'
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 2e15f26e..fc92ad54 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -46,9 +46,4 @@ module ApplicationHelper
def omniauth_login_url(provider)
"#{relative_root}/auth/#{provider}"
end
-
- # Whether the current page is the page of a room/meeting or not
- def on_room_or_meeting_page?
- params[:id].present?
- end
end
diff --git a/app/helpers/landing_helper.rb b/app/helpers/landing_helper.rb
index a351c30a..b2b3e74a 100644
--- a/app/helpers/landing_helper.rb
+++ b/app/helpers/landing_helper.rb
@@ -15,7 +15,5 @@
# with BigBlueButton; if not, see .
module LandingHelper
- def new_meeting_token
- rand.to_s[2..10]
- end
+
end
diff --git a/app/views/landing/index.html.erb b/app/views/landing/index.html.erb
index ae3a4825..38e90ba4 100644
--- a/app/views/landing/index.html.erb
+++ b/app/views/landing/index.html.erb
@@ -39,9 +39,11 @@
<% end %>
-
- <%= render 'shared/signup' %>
-
+ <% if omniauth_providers_configured.present? %>
+
+ <%= render 'shared/signup' %>
+
+ <% end %>
diff --git a/config/routes.rb b/config/routes.rb
index b4f7501a..f9e764ad 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -23,7 +23,7 @@ Rails.application.routes.draw do
get '/users/logout', to: 'sessions#destroy', as: :user_logout
match '/auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
- get '/auth/failure', to: 'landing#auth_failure'
+ get '/auth/failure', to: 'sessions#auth_failure'
# There are two resources [meetings|rooms]
# meetings offer a landing page for NON authenticated users to create and join session in BigBlueButton
diff --git a/test/controllers/bbb_controller_test.rb b/test/controllers/bbb_controller_test.rb
index 241d31d6..c7b2e4a3 100644
--- a/test/controllers/bbb_controller_test.rb
+++ b/test/controllers/bbb_controller_test.rb
@@ -17,13 +17,158 @@
require 'test_helper'
class BbbControllerTest < ActionController::TestCase
- # test "should get join" do
- # get :join
- # assert_response :success
- # end
+ include BbbApi
+
+ setup do
+ @meeting_id = 'test_id'
+ @user = users :user1
+ @name = 'test_name'
+ @recording = 'test_recording'
+ end
+
+ test "should get join URL from join for meeting" do
+ BbbController.any_instance.expects(:bbb_join_url)
+ .with() do |token, full_name, opts|
+ token == @meeting_id && full_name == @name && opts[:user_is_moderator]
+ end.returns(success_join_res('correct_url')).once
+
+ get :join, params: { id: @meeting_id, resource: 'meetings', name: @name }
+ assert_response :success
+
+ result = JSON.parse(response.body).deep_symbolize_keys
+ assert_equal 'correct_url', result[:response][:join_url]
+ end
+
+ test "should get join URL from join for authenticated meeting" do
+ login @user
+
+ BbbController.any_instance.expects(:bbb_join_url)
+ .with() do |token, full_name, opts|
+ token == meeting_token(@user, @meeting_id) && opts[:wait_for_moderator] && opts[:user_is_moderator] && opts[:meeting_recorded]
+ end.returns(success_join_res('correct_url')).once
+
+ get :join, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms', name: @name }
+ assert_response :success
+ end
+
+ test "should wati for moderator on join for authenticated meeting when not room owner" do
+ BbbController.any_instance.expects(:bbb_join_url)
+ .with() do |token, full_name, opts|
+ opts[:wait_for_moderator] && !opts[:user_is_moderator]
+ end.returns(success_join_res('correct_url')).once
+
+ get :join, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms', name: @name }
+ assert_response :success
+ end
+
+ test "should end meeting" do
+ login @user
+
+ BbbController.any_instance.expects(:bbb_end_meeting)
+ .with() do |token|
+ token == meeting_token(@user, @meeting_id)
+ end.returns({status: :ok}).once
+
+ get :end, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms' }
+ assert_response :success
+ end
+
+ test "should not end meeting for unauthorized user" do
+ login users :user2
+
+ get :end, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms' }
+ assert_response :unauthorized
+ end
+
+ test "should get recordings" do
+
+ BbbController.any_instance.expects(:bbb_get_recordings)
+ .returns({status: :ok, recordings: []}).once
+
+ get :recordings, params: { room_id: @user.encrypted_id, resource: 'rooms' }
+ assert_response :success
+ end
+
+ test "should update recording" do
+ login @user
+
+ BbbController.any_instance.expects(:bbb_get_recordings)
+ .returns({status: :ok, recordings: [{recordID: @recording}]}).once
+
+ BbbController.any_instance.expects(:bbb_update_recordings)
+ .returns({status: :ok}).once
+
+ patch :update_recordings, params: { room_id: @user.encrypted_id, resource: 'rooms', record_id: @recording }
+ assert_response :success
+ end
+
+ test "should delete recording" do
+ login @user
+
+ BbbController.any_instance.expects(:bbb_get_recordings)
+ .returns({status: :ok, recordings: [{recordID: @recording}]}).at_least_once
+
+ BbbController.any_instance.expects(:bbb_delete_recordings)
+ .returns({status: :ok}).once
+
+ delete :delete_recordings, params: { room_id: @user.encrypted_id, resource: 'rooms', record_id: @recording }
+ assert_response :success
+ end
+
+ test "should not delete recording if unauthorized" do
+ login users :user2
+
+ BbbController.any_instance.expects(:bbb_get_recordings)
+ .returns({status: :ok, recordings: [{recordID: @recording}]}).at_least_once
+
+ BbbController.any_instance.expects(:bbb_delete_recordings)
+ .returns({status: :ok}).once
+
+ delete :delete_recordings, params: { room_id: @user.encrypted_id, resource: 'rooms', record_id: @recording }
+ assert_response :unauthorized
+ end
+
+ test "should not delete recording if not owner" do
+ login @user
+
+ BbbController.any_instance.expects(:bbb_get_recordings)
+ .returns({status: :ok, recordings: []}).once
+
+ BbbController.any_instance.expects(:bbb_update_recordings)
+ .returns({status: :ok}).once
+
+ patch :delete_recordings, params: { room_id: @user.encrypted_id, resource: 'rooms', record_id: @recording }
+ assert_response :not_found
+ end
+
+ test "should return success on invalid checksum" do
+
+ BbbController.any_instance.expects(:treat_callback_event).never
+
+ post :callback, params: { room_id: @user.encrypted_id, resource: 'rooms', id: @meeting_id, event: {} }
+ assert_response :success
+ end
+
+ # TODO fix this test
+ # test "should send notification on valid callback" do
#
- # test "should get end" do
- # get :close
+ # BbbController.any_instance.expects(:treat_callback_event).once
+ #
+ # BbbController.any_instance.expects(:validate_checksum)
+ # .returns(true).once
+ #
+ # post :callback, params: { room_id: @user.encrypted_id, resource: 'rooms', id: @meeting_id, event: {} }
# assert_response :success
# end
+
+ private
+
+ def meeting_token(user, id)
+ "#{user.encrypted_id}-#{id}"
+ end
+
+ def login(user)
+ session[:user_id] = user.id
+ @current_user = user
+ end
end
diff --git a/test/controllers/landing_controller_test.rb b/test/controllers/landing_controller_test.rb
index 4a698af5..648921b9 100644
--- a/test/controllers/landing_controller_test.rb
+++ b/test/controllers/landing_controller_test.rb
@@ -19,7 +19,7 @@ require 'test_helper'
class LandingControllerTest < ActionController::TestCase
setup do
- @meeting_id = rand 100000000..999999999
+ @meeting_id = 'test_id'
@user = users :user1
end
@@ -38,14 +38,27 @@ class LandingControllerTest < ActionController::TestCase
assert_response :success
end
+ test "should get meeting room" do
+ get :resource, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms' }
+ assert_response :success
+ end
+
test "should get wait for moderator" do
- get :wait_for_moderator, params: { room_id: @user.encrypted_id, id: 'room1', resource: 'rooms' }
+ get :wait_for_moderator, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms' }
assert_response :success
end
test "should get session status refresh" do
- get :wait_for_moderator, params: { room_id: @user.encrypted_id, id: 'room1', resource: 'rooms' }
+ get :session_status_refresh, params: { room_id: @user.encrypted_id, id: @meeting_id, resource: 'rooms' }
assert_response :success
end
+ test "should fallback to en-US locale if locale is en" do
+ request.headers["Accept-Language"] = 'en'
+ get :index, params: {resource: 'meetings'}
+ assert_response :success
+
+ assert css_select('html').attribute('lang').value, 'en'
+ end
+
end
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
new file mode 100644
index 00000000..544c2b77
--- /dev/null
+++ b/test/controllers/sessions_controller_test.rb
@@ -0,0 +1,45 @@
+require 'test_helper'
+
+class SessionsControllerTest < ActionController::TestCase
+
+ setup do
+ @user = users :user1
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should redirect to home on auth failture" do
+ get "auth_failure"
+ assert_redirected_to root_path
+ end
+
+ test "should not create session without omniauth env set" do
+ post :create, params: {provider: 'google'}
+ assert_redirected_to root_path
+ end
+
+ test "should create session and user" do
+ provider = 'google'
+ email = 'new_user@email.com'
+ request.env['omniauth.auth'] = {'uid' => 'uid', 'provider' => provider,
+ 'info' => {'name' => 'name', 'email' => email}}
+
+ post :create, params: {provider: provider}
+
+ new_user = User.find_by email: email
+
+ assert_not_nil new_user
+ assert_redirected_to meeting_room_path(id: new_user.encrypted_id, resource: 'rooms')
+ assert_equal new_user.id, session[:user_id]
+ end
+
+ test "should destroy current session" do
+ session[:user_id] = @user.id
+ get :destroy
+ assert_redirected_to root_path
+ assert_nil session[:user_id]
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index da9519e1..61a1b471 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -15,8 +15,20 @@
# with BigBlueButton; if not, see .
ENV['RAILS_ENV'] ||= 'test'
+
+require 'simplecov'
+SimpleCov.start do
+ add_group 'Models', 'app/models'
+ add_group 'Controllers', 'app/controllers'
+ add_group 'Helpers', 'app/helpers'
+ add_group 'Config', 'config/'
+ add_group 'Libraries', 'lib/'
+ add_group 'Tests', 'test/'
+end
+
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
+require "mocha/test_unit"
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.