diff --git a/.gitignore b/.gitignore index 2dfd8836..385c1850 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,7 @@ # Ignore environment configuration. .env + +# IDEs +.idea +.idea/** diff --git a/Gemfile b/Gemfile index 538c9b49..47ce2f1c 100644 --- a/Gemfile +++ b/Gemfile @@ -26,7 +26,7 @@ gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.2' # See https://github.com/rails/execjs#readme for more supported runtimes -# gem 'therubyracer', platforms: :ruby +gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' @@ -47,6 +47,7 @@ gem 'bcrypt', '~> 3.1.7' gem 'omniauth' gem 'omniauth-twitter' gem 'omniauth-google-oauth2' +gem 'omniauth-bn-launcher', '~> 0.1.0' # BigBlueButton API wrapper. gem 'bigbluebutton-api-ruby' diff --git a/Gemfile.lock b/Gemfile.lock index fe663602..9b2ec5b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -42,7 +42,7 @@ GEM tzinfo (~> 1.1) arel (7.1.4) ast (2.4.0) - autoprefixer-rails (8.6.2) + autoprefixer-rails (8.6.4) execjs bcrypt (3.1.12) bigbluebutton-api-ruby (1.6.0) @@ -64,9 +64,9 @@ GEM concurrent-ruby (1.0.5) crass (1.0.4) diff-lcs (1.3) - dotenv (2.4.0) - dotenv-rails (2.4.0) - dotenv (= 2.4.0) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) railties (>= 3.2, < 6.0) erubis (2.7.0) execjs (2.7.0) @@ -94,6 +94,7 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) jwt (1.5.6) + libv8 (3.16.14.19) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -110,7 +111,7 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) nio4r (2.3.1) - nokogiri (1.8.2) + nokogiri (1.8.3) mini_portile2 (~> 2.3.0) oauth (0.5.4) oauth2 (1.4.0) @@ -122,6 +123,9 @@ GEM omniauth (1.8.1) hashie (>= 3.4.6, < 3.6.0) rack (>= 1.6.2, < 3) + omniauth-bn-launcher (0.1.0) + omniauth (~> 1.3, >= 1.3.2) + omniauth-oauth2 (= 1.5.0) omniauth-google-oauth2 (0.5.3) jwt (>= 1.5) omniauth (>= 1.1.1) @@ -178,6 +182,7 @@ GEM rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) redis (3.3.5) + ref (2.0.0) rspec-core (3.7.1) rspec-support (~> 3.7.0) rspec-expectations (3.7.0) @@ -222,7 +227,7 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (3.7.1) + sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.1) @@ -232,6 +237,9 @@ GEM sqlite3 (1.3.13) tabler-rubygem (0.1.2) autoprefixer-rails (>= 6.0.3) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) + ref thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) @@ -240,7 +248,7 @@ GEM turbolinks-source (5.1.0) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.11) + uglifier (4.1.12) execjs (>= 0.3.0, < 3) unicode-display_width (1.4.0) web-console (3.6.2) @@ -270,6 +278,7 @@ DEPENDENCIES jquery-rails listen (~> 3.0.5) omniauth + omniauth-bn-launcher (~> 0.1.0) omniauth-google-oauth2 omniauth-twitter pg (~> 0.18) @@ -285,6 +294,7 @@ DEPENDENCIES spring-watcher-listen (~> 2.0.0) sqlite3 tabler-rubygem + therubyracer turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index d5f11bdb..432084a4 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -22,4 +22,23 @@ module SessionsHelper def current_user @current_user ||= User.find_by(id: session[:user_id]) end + + def generate_checksum(customer_name, redirect_url, secret) + string = customer_name + redirect_url + secret + OpenSSL::Digest.digest('sha1', string).unpack("H*").first + end + + def parse_customer_name(hostname) + provider = hostname.split('.') + provider.first == 'www' ? provider.second : provider.first + end + + def omniauth_options(env) + gl_redirect_url = env["rack.url_scheme"] + "://" + env["SERVER_NAME"] + ":" + env["SERVER_PORT"] + env['omniauth.strategy'].options[:customer] = parse_customer_name env["SERVER_NAME"] + env['omniauth.strategy'].options[:gl_redirect_url] = gl_redirect_url + env['omniauth.strategy'].options[:default_callback_url] = Rails.configuration.gl_callback_url + env['omniauth.strategy'].options[:checksum] = generate_checksum parse_customer_name(env["SERVER_NAME"]), + gl_redirect_url, Rails.configuration.launcher_secret + end end diff --git a/app/models/user.rb b/app/models/user.rb index f5c086cd..53413b23 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -22,7 +22,9 @@ class User < ApplicationRecord class << self # Generates a user from omniauth. def from_omniauth(auth) - find_or_initialize_by(social_uid: auth['uid'], provider: auth['provider']).tap do |u| + # Provider is the customer name if in loadbalanced config mode + provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : auth['provider'] + find_or_initialize_by(social_uid: auth['uid'], provider: provider).tap do |u| u.name = send("#{auth['provider']}_name", auth) unless u.name u.username = send("#{auth['provider']}_username", auth) unless u.username u.email = send("#{auth['provider']}_email", auth) @@ -65,6 +67,22 @@ class User < ApplicationRecord def google_image(auth) auth['info']['image'] end + + def bn_launcher_name(auth) + auth['info']['name'] + end + + def bn_launcher_username(auth) + auth['info']['username'] + end + + def bn_launcher_email(auth) + auth['info']['email'] + end + + def bn_launcher_image(auth) + auth['info']['image'] + end end # Retrives a list of all a users rooms that are not the main room, sorted by last session date. diff --git a/app/views/shared/_header.html.erb b/app/views/shared/_header.html.erb index 78e5217c..0f2666ab 100644 --- a/app/views/shared/_header.html.erb +++ b/app/views/shared/_header.html.erb @@ -44,7 +44,11 @@ <% else %> - <%= link_to "Login", "#loginModal", :class => "btn btn-pill btn-outline-primary mx-2", "data-toggle": "modal" %> + <% if Rails.configuration.omniauth_bn_launcher && !current_user %> + <%= link_to "Login", "#{Rails.configuration.relative_url_root}/auth/bn_launcher", :class => "btn btn-pill btn-outline-primary mx-2" %> + <% else %> + <%= link_to "Login", "#loginModal", :class => "btn btn-pill btn-outline-primary mx-2", "data-toggle": "modal" %> + <% end %> <% if allow_user_signup? %> <%= link_to "Signup", signup_path, :class => "btn btn-pill btn-outline-primary mx-2" %> diff --git a/bin/start b/bin/start index a0d04505..c5c5a8e1 100755 --- a/bin/start +++ b/bin/start @@ -1,4 +1,11 @@ #!/bin/bash +if [ "$RAILS_ENV" = "production" ] && [ "$DB_ADAPTER" = "postgresql" ]; then + while ! curl http://$DB_HOST:${DB_PORT:-5432}/ 2>&1 | grep '52' + do + echo "Waiting for postgres to start up ..." + sleep 1 + done +fi bundle exec rake db:create if ! bundle exec rake db:migrate ; then diff --git a/config/application.rb b/config/application.rb index 7521eea8..27fb26e0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -18,12 +18,14 @@ module Greenlight config.exceptions_app = routes config.loadbalanced_configuration = ENV["LOADBALANCER_ENDPOINT"].present? && ENV["LOADBALANCER_SECRET"].present? - + # The default callback url that bn launcher will redirect to + config.gl_callback_url = ENV["GL_CALLBACK_URL"] # Setup BigBlueButton configuration. if config.loadbalanced_configuration # Fetch credentials from a loadbalancer based on provider. config.loadbalancer_endpoint = ENV["LOADBALANCER_ENDPOINT"] config.loadbalancer_secret = ENV["LOADBALANCER_SECRET"] + config.launcher_secret = ENV["LAUNCHER_SECRET"] else # Default credentials (test-install.blindsidenetworks.com/bigbluebutton). config.bigbluebutton_endpoint_default = "http://test-install.blindsidenetworks.com/bigbluebutton/api/" diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index 16f154ad..0fa094ea 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -6,9 +6,21 @@ Rails.application.config.providers = [:google, :twitter] # Set which providers are configured. Rails.application.config.omniauth_google = ENV['GOOGLE_OAUTH2_ID'].present? && ENV['GOOGLE_OAUTH2_SECRET'].present? Rails.application.config.omniauth_twitter = ENV['TWITTER_ID'].present? && ENV['TWITTER_SECRET'].present? +Rails.application.config.omniauth_bn_launcher = Rails.configuration.loadbalanced_configuration + +SETUP_PROC = lambda do |env| + SessionsController.helpers.omniauth_options env +end # Setup the Omniauth middleware. Rails.application.config.middleware.use OmniAuth::Builder do + if Rails.configuration.omniauth_bn_launcher + provider :bn_launcher, client_id: ENV['CLIENT_ID'], + client_secret: ENV['CLIENT_SECRET'], + client_options: { site: ENV['BN_LAUNCHER_REDIRECT_URI'] }, + setup: SETUP_PROC + end + provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET'] provider :google_oauth2, ENV['GOOGLE_OAUTH2_ID'], ENV['GOOGLE_OAUTH2_SECRET'], diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 8713b215..e6607510 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -61,12 +61,24 @@ describe SessionsController, type: :controller do }, ) + OmniAuth.config.mock_auth[:bn_launcher] = OmniAuth::AuthHash.new( + provider: "bn_launcher", + uid: "bn-launcher-user", + info: { + email: "user1@google.com", + name: "User1", + nickname: "nick", + image: "touch.png", + customer: 'ocps', + } + ) + OmniAuth.config.on_failure = proc { |env| OmniAuth::FailureEndpoint.new(env).redirect_to_failure } end - it "should create and login user with omniauth" do + it "should create and login user with omniauth twitter" do request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter] get :omniauth, params: { provider: :twitter } @@ -76,6 +88,16 @@ describe SessionsController, type: :controller do expect(@request.session[:user_id]).to eql(u.id) end + it "should create and login user with omniauth bn launcher" do + request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:bn_launcher] + get :omniauth, params: { provider: 'bn_launcher' } + + u = User.last + expect(u.provider).to eql("ocps") + expect(u.email).to eql("user1@google.com") + expect(@request.session[:user_id]).to eql(u.id) + end + it "should redirect to root on invalid omniauth login" do request.env["omniauth.auth"] = :invalid_credentials get :omniauth, params: { provider: :twitter } @@ -83,10 +105,16 @@ describe SessionsController, type: :controller do expect(response).to redirect_to(root_path) end - it "should not create session without omniauth env set" do + it "should not create session without omniauth env set for google" do get :omniauth, params: { provider: 'google' } expect(response).to redirect_to(root_path) end + + it "should not create session without omniauth env set for bn_launcher" do + get :omniauth, params: { provider: 'bn_launcher' } + + expect(response).to redirect_to(root_path) + end end end