forked from External/greenlight
GRN-80: Allow local accounts on multitenant (#428)
* Changed the way the omniauth providers are declared * Allow local authentication for multitenant mode based on customer settings * Cleanead up code mandated by rubocop * Completed implementation for signin and added the one for signup * Fixed issue with rubocop * Renamed customer_name to lb_user * Renamed lb_user -> user_domain, fixed issue with signup controller, email verification WAS NOT implemented * Completed implementation of email_verification * Fixed rubocop issue * Final update * Fix for test with loadbalancer * Make sure loadbalancer mockup is only used when env defined * Fix for test on rooms_controller * Fixed most of the test failing on multitenant env * Fixed issue detected by rubocop * Fixed issue with activation tockens not working on resend * Fixed new issue found by rubocop * Updated travis script * Harcoded credentials for mockup * Updated expectation on start_session * Fixed issue with duplication of home room * Updated script for rubocop * Restored Gemfile
This commit is contained in:
@ -27,7 +27,7 @@ class AccountActivationsController < ApplicationController
|
||||
|
||||
# GET /account_activations/edit
|
||||
def edit
|
||||
if @user && !@user.email_verified? && @user.authenticated?(:activation, params[:token])
|
||||
if @user && !@user.activated? && @user.authenticated?(:activation, params[:token])
|
||||
@user.activate
|
||||
|
||||
flash[:success] = I18n.t("verify.activated") + " " + I18n.t("verify.signin")
|
||||
@ -40,7 +40,7 @@ class AccountActivationsController < ApplicationController
|
||||
|
||||
# GET /account_activations/resend
|
||||
def resend
|
||||
if @user.email_verified
|
||||
if @user.activated?
|
||||
flash[:alert] = I18n.t("verify.already_verified")
|
||||
else
|
||||
begin
|
||||
@ -67,10 +67,10 @@ class AccountActivationsController < ApplicationController
|
||||
end
|
||||
|
||||
def email_params
|
||||
params.require(:email).permit(:token)
|
||||
params.require(:email).permit(:email, :token)
|
||||
end
|
||||
|
||||
def find_user
|
||||
@user = User.find_by!(email: params[:email], provider: "greenlight")
|
||||
@user = User.find_by!(email: params[:email], provider: @user_domain)
|
||||
end
|
||||
end
|
||||
|
@ -23,6 +23,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
before_action :migration_error?
|
||||
before_action :set_locale
|
||||
before_action :set_user_domain
|
||||
|
||||
# Force SSL for loadbalancer configurations.
|
||||
before_action :redirect_to_https
|
||||
@ -68,16 +69,11 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# Determines if the BigBlueButton endpoint is configured (or set to default).
|
||||
def bigbluebutton_endpoint_default?
|
||||
return false if loadbalanced_configuration?
|
||||
return false if Rails.configuration.loadbalanced_configuration
|
||||
Rails.configuration.bigbluebutton_endpoint_default == Rails.configuration.bigbluebutton_endpoint
|
||||
end
|
||||
helper_method :bigbluebutton_endpoint_default?
|
||||
|
||||
def loadbalanced_configuration?
|
||||
Rails.configuration.loadbalanced_configuration
|
||||
end
|
||||
helper_method :loadbalanced_configuration?
|
||||
|
||||
def recording_thumbnails?
|
||||
Rails.configuration.recording_thumbnails
|
||||
end
|
||||
@ -106,6 +102,17 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def redirect_to_https
|
||||
redirect_to protocol: "https://" if loadbalanced_configuration? && request.headers["X-Forwarded-Proto"] == "http"
|
||||
if Rails.configuration.loadbalanced_configuration && request.headers["X-Forwarded-Proto"] == "http"
|
||||
redirect_to protocol: "https://"
|
||||
end
|
||||
end
|
||||
|
||||
def set_user_domain
|
||||
@user_domain = if Rails.env.test? || !Rails.configuration.loadbalanced_configuration
|
||||
"greenlight"
|
||||
else
|
||||
parse_user_domain(request.env["SERVER_NAME"])
|
||||
end
|
||||
end
|
||||
helper_method :set_user_domain
|
||||
end
|
||||
|
@ -84,7 +84,7 @@ class PasswordResetsController < ApplicationController
|
||||
|
||||
# Confirms a valid user.
|
||||
def valid_user
|
||||
unless current_user&.email_verified && current_user.authenticated?(:reset, params[:id])
|
||||
unless current_user&.activated? && current_user.authenticated?(:reset, params[:id])
|
||||
redirect_to root_url
|
||||
end
|
||||
end
|
||||
|
@ -224,12 +224,12 @@ class RoomsController < ApplicationController
|
||||
|
||||
def validate_verified_email
|
||||
if current_user
|
||||
redirect_to account_activation_path(current_user) unless current_user.email_verified
|
||||
redirect_to account_activation_path(current_user) unless current_user.activated?
|
||||
end
|
||||
end
|
||||
|
||||
def verify_room_owner_verified
|
||||
unless @room.owner.email_verified
|
||||
unless @room.owner.activated?
|
||||
flash[:alert] = t("room.unavailable")
|
||||
|
||||
if current_user
|
||||
|
@ -27,18 +27,13 @@ class SessionsController < ApplicationController
|
||||
|
||||
# POST /users/login
|
||||
def create
|
||||
user = User.find_by(email: session_params[:email])
|
||||
if user && !user.greenlight_account?
|
||||
redirect_to root_path, alert: I18n.t("invalid_login_method")
|
||||
elsif user.try(:authenticate, session_params[:password])
|
||||
if user.email_verified
|
||||
login(user)
|
||||
else
|
||||
redirect_to(account_activation_path(email: user.email)) && return
|
||||
end
|
||||
else
|
||||
redirect_to root_path, alert: I18n.t("invalid_credentials")
|
||||
end
|
||||
user = User.find_by(email: session_params[:email], provider: @user_domain)
|
||||
redirect_to(root_path, alert: I18n.t("invalid_user")) && return unless user
|
||||
redirect_to(root_path, alert: I18n.t("invalid_login_method")) && return unless user.greenlight_account?
|
||||
redirect_to(root_path, alert: I18n.t("invalid_credentials")) && return unless user.try(:authenticate,
|
||||
session_params[:password])
|
||||
redirect_to(account_activation_path(email: user.email)) && return unless user.activated?
|
||||
login(user)
|
||||
end
|
||||
|
||||
# GET/POST /auth/:provider/callback
|
||||
|
@ -28,40 +28,24 @@ class UsersController < ApplicationController
|
||||
return unless Rails.configuration.allow_user_signup
|
||||
|
||||
@user = User.new(user_params)
|
||||
@user.provider = "greenlight"
|
||||
@user.provider = @user_domain
|
||||
|
||||
# Check if user already exists
|
||||
if User.exists?(email: user_params[:email], provider: @user.provider)
|
||||
existing_user = User.find_by!(email: user_params[:email], provider: @user.provider)
|
||||
if Rails.configuration.enable_email_verification && !existing_user.email_verified?
|
||||
# User exists but is not verified
|
||||
redirect_to(account_activation_path(email: existing_user.email)) && return
|
||||
else
|
||||
# User already exists and is verified
|
||||
# Attempt to save so that the correct errors appear
|
||||
@user.save
|
||||
# Handle error on user creation.
|
||||
render(:new) && return unless @user.save
|
||||
|
||||
render(:new) && return
|
||||
end
|
||||
elsif Rails.configuration.enable_email_verification && @user.save
|
||||
begin
|
||||
@user.send_activation_email(verification_link)
|
||||
rescue => e
|
||||
logger.error "Error in email delivery: #{e}"
|
||||
flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error"))
|
||||
else
|
||||
flash[:success] = I18n.t("email_sent")
|
||||
end
|
||||
# Sign in automatically if email verification is disabled.
|
||||
login(@user) && return unless Rails.configuration.enable_email_verification
|
||||
|
||||
redirect_to(root_path) && return
|
||||
elsif @user.save
|
||||
# User doesn't exist and email verification is turned off
|
||||
@user.activate
|
||||
login(@user)
|
||||
# Start email verification and redirect to root.
|
||||
begin
|
||||
@user.send_activation_email(verification_link)
|
||||
rescue => e
|
||||
logger.error "Error in email delivery: #{e}"
|
||||
flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error"))
|
||||
else
|
||||
# Handle error on user creation.
|
||||
render(:new) && return
|
||||
flash[:success] = I18n.t("email_sent")
|
||||
end
|
||||
redirect_to(root_path)
|
||||
end
|
||||
|
||||
# GET /signup
|
||||
|
@ -16,8 +16,11 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'bbb_api'
|
||||
|
||||
module ApplicationHelper
|
||||
include MeetingsHelper
|
||||
include BbbApi
|
||||
|
||||
# Gets all configured omniauth providers.
|
||||
def configured_providers
|
||||
@ -71,4 +74,14 @@ module ApplicationHelper
|
||||
|
||||
markdown.render(text).html_safe
|
||||
end
|
||||
|
||||
def allow_greenlight_accounts?
|
||||
return true unless Rails.configuration.loadbalanced_configuration
|
||||
return false unless Rails.configuration.allow_user_signup
|
||||
# No need to retrieve the provider info if the provider is whitelisted
|
||||
return true if launcher_allow_user_signup_whitelisted?(@user_domain)
|
||||
# Proceed with retrieving the provider info
|
||||
provider_info = retrieve_provider_info(@user_domain, 'api2', 'getUserGreenlightCredentials')
|
||||
provider_info['provider'] == 'greenlight'
|
||||
end
|
||||
end
|
||||
|
@ -31,7 +31,7 @@ module SessionsHelper
|
||||
|
||||
# If email verification is disabled, or the user has verified, go to their room
|
||||
def check_email_verified(user)
|
||||
if !Rails.configuration.enable_email_verification || user.email_verified
|
||||
if user.activated?
|
||||
redirect_to user.main_room
|
||||
else
|
||||
redirect_to resend_path
|
||||
@ -48,24 +48,24 @@ module SessionsHelper
|
||||
@current_user ||= User.find_by(id: session[:user_id])
|
||||
end
|
||||
|
||||
def generate_checksum(customer_name, redirect_url, secret)
|
||||
string = customer_name + redirect_url + secret
|
||||
def generate_checksum(user_domain, redirect_url, secret)
|
||||
string = user_domain + 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
|
||||
def parse_user_domain(hostname)
|
||||
hostname.split('.').first
|
||||
end
|
||||
|
||||
def omniauth_options(env)
|
||||
gl_redirect_url = (Rails.env.production? ? "https" : env["rack.url_scheme"]) + "://" + env["SERVER_NAME"] + ":" +
|
||||
env["SERVER_PORT"]
|
||||
env['omniauth.strategy'].options[:customer] = parse_customer_name env["SERVER_NAME"]
|
||||
user_domain = parse_user_domain(env["SERVER_NAME"])
|
||||
env['omniauth.strategy'].options[:customer] = user_domain
|
||||
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
|
||||
env['omniauth.strategy'].options[:checksum] = generate_checksum(user_domain, gl_redirect_url,
|
||||
Rails.configuration.launcher_secret)
|
||||
end
|
||||
|
||||
def google_omniauth_hd(env, hd)
|
||||
|
@ -19,77 +19,6 @@
|
||||
module APIConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
RETURNCODE_SUCCESS = "SUCCESS"
|
||||
|
||||
def bbb_endpoint
|
||||
Rails.configuration.bigbluebutton_endpoint
|
||||
end
|
||||
|
||||
def bbb_secret
|
||||
Rails.configuration.bigbluebutton_secret
|
||||
end
|
||||
|
||||
# Sets a BigBlueButtonApi object for interacting with the API.
|
||||
def bbb
|
||||
@bbb ||= if Rails.configuration.loadbalanced_configuration
|
||||
if instance_of? Room
|
||||
# currently in the Room Model
|
||||
lb_user = retrieve_loadbalanced_credentials(owner.provider)
|
||||
elsif instance_of? User
|
||||
# currently in the User Model
|
||||
lb_user = retrieve_loadbalanced_credentials(provider)
|
||||
end
|
||||
BigBlueButton::BigBlueButtonApi.new(remove_slash(lb_user["apiURL"]), lb_user["secret"], "0.8")
|
||||
else
|
||||
BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8")
|
||||
end
|
||||
end
|
||||
|
||||
# Rereives the loadbalanced BigBlueButton credentials for a user.
|
||||
def retrieve_loadbalanced_credentials(provider)
|
||||
# Include Omniauth accounts under the Greenlight provider.
|
||||
provider = "greenlight" if Rails.configuration.providers.include?(provider.to_sym)
|
||||
|
||||
# Build the URI.
|
||||
uri = encode_bbb_url(
|
||||
Rails.configuration.loadbalancer_endpoint + "getUser",
|
||||
Rails.configuration.loadbalancer_secret,
|
||||
name: provider
|
||||
)
|
||||
|
||||
# Make the request.
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
http.use_ssl = (uri.scheme == 'https')
|
||||
response = http.get(uri.request_uri)
|
||||
|
||||
unless response.is_a?(Net::HTTPSuccess)
|
||||
raise "Error retrieving provider credentials: #{response.code} #{response.message}"
|
||||
end
|
||||
|
||||
# Parse XML.
|
||||
doc = XmlSimple.xml_in(response.body, 'ForceArray' => false)
|
||||
|
||||
# Return the user credentials if the request succeeded on the loadbalancer.
|
||||
return doc['user'] if doc['returncode'] == RETURNCODE_SUCCESS
|
||||
|
||||
raise "User with provider #{provider} does not exist." if doc['messageKey'] == "noSuchUser"
|
||||
raise "API call #{url} failed with #{doc['messageKey']}."
|
||||
end
|
||||
|
||||
# Builds a request to retrieve credentials from the load balancer.
|
||||
def encode_bbb_url(base_url, secret, params)
|
||||
encoded_params = OAuth::Helper.normalize(params)
|
||||
string = "getUser" + encoded_params + secret
|
||||
checksum = OpenSSL::Digest.digest('sha1', string).unpack("H*").first
|
||||
|
||||
URI.parse("#{base_url}?#{encoded_params}&checksum=#{checksum}")
|
||||
end
|
||||
|
||||
# Removes trailing forward slash from a URL.
|
||||
def remove_slash(s)
|
||||
s.nil? ? nil : s.chomp("/")
|
||||
end
|
||||
|
||||
# Format recordings to match their current use in the app
|
||||
def format_recordings(api_res)
|
||||
api_res[:recordings].each do |r|
|
||||
|
@ -16,8 +16,11 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'bbb_api'
|
||||
|
||||
class Room < ApplicationRecord
|
||||
include ::APIConcern
|
||||
include ::BbbApi
|
||||
|
||||
before_create :setup
|
||||
|
||||
|
@ -16,13 +16,15 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License along
|
||||
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'bbb_api'
|
||||
|
||||
class User < ApplicationRecord
|
||||
include ::APIConcern
|
||||
include ::BbbApi
|
||||
|
||||
attr_accessor :reset_token, :activation_token
|
||||
after_create :create_home_room_if_verified
|
||||
attr_accessor :reset_token
|
||||
after_create :initialize_main_room
|
||||
before_save { email.try(:downcase!) }
|
||||
before_create :create_activation_digest
|
||||
|
||||
before_destroy :destroy_rooms
|
||||
|
||||
@ -125,8 +127,11 @@ class User < ApplicationRecord
|
||||
def activate
|
||||
update_attribute(:email_verified, true)
|
||||
update_attribute(:activated_at, Time.zone.now)
|
||||
end
|
||||
|
||||
initialize_main_room
|
||||
def activated?
|
||||
return true unless Rails.configuration.enable_email_verification
|
||||
email_verified
|
||||
end
|
||||
|
||||
def send_activation_email(url)
|
||||
@ -180,7 +185,17 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def greenlight_account?
|
||||
provider == "greenlight"
|
||||
return provider == "greenlight" unless Rails.configuration.loadbalanced_configuration
|
||||
# No need to retrive the provider info if the provider is whitelisted
|
||||
return true if launcher_allow_user_signup_whitelisted?(provider)
|
||||
# Proceed with fetching the provider info
|
||||
provider_info = retrieve_provider_info(provider, 'api2', 'getUserGreenlightCredentials')
|
||||
provider_info['provider'] == 'greenlight'
|
||||
end
|
||||
|
||||
def activation_token
|
||||
# Create the token.
|
||||
create_reset_activation_digest(User.new_token)
|
||||
end
|
||||
|
||||
def self.digest(string)
|
||||
@ -195,10 +210,11 @@ class User < ApplicationRecord
|
||||
|
||||
private
|
||||
|
||||
def create_activation_digest
|
||||
# Create the token and digest.
|
||||
self.activation_token = User.new_token
|
||||
self.activation_digest = User.digest(activation_token)
|
||||
def create_reset_activation_digest(token)
|
||||
# Create the digest and persist it.
|
||||
self.activation_digest = User.digest(token)
|
||||
save
|
||||
token
|
||||
end
|
||||
|
||||
# Destory a users rooms when they are removed.
|
||||
@ -206,16 +222,9 @@ class User < ApplicationRecord
|
||||
rooms.destroy_all
|
||||
end
|
||||
|
||||
# Assigns the user a BigBlueButton id and a home room if verified
|
||||
def create_home_room_if_verified
|
||||
self.uid = "gl-#{(0...12).map { (65 + rand(26)).chr }.join.downcase}"
|
||||
|
||||
initialize_main_room if email_verified
|
||||
save
|
||||
end
|
||||
|
||||
# Initializes a room for the user and assign a BigBlueButton user id.
|
||||
def initialize_main_room
|
||||
self.uid = "gl-#{(0...12).map { (65 + rand(26)).chr }.join.downcase}"
|
||||
self.main_room = Room.create!(owner: self, name: I18n.t("home_room"))
|
||||
save
|
||||
end
|
||||
|
@ -56,21 +56,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<% if Rails.configuration.omniauth_bn_launcher %>
|
||||
<%= link_to t("login"), omniauth_login_url(:bn_launcher), :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% elsif Rails.configuration.omniauth_ldap %>
|
||||
<%= link_to t("login"), omniauth_login_url(:ldap), :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% else %>
|
||||
<% if Rails.configuration.omniauth_ldap %>
|
||||
<%= link_to t("login"), omniauth_login_url(:ldap), :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% elsif allow_greenlight_accounts? %>
|
||||
<%= link_to t("login"), "#loginModal", :class => "btn btn-pill btn-outline-primary mx-2", "data-toggle": "modal" %>
|
||||
<% else %>
|
||||
<%= link_to t("login"), omniauth_login_url(:bn_launcher), :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% end %>
|
||||
|
||||
<% if allow_user_signup? %>
|
||||
<%= link_to t("signup.title"), signup_path, :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% end %>
|
||||
<% if allow_user_signup? && allow_greenlight_accounts? %>
|
||||
<%= link_to t("signup.title"), signup_path, :class => "btn btn-pill btn-outline-primary mx-2" %>
|
||||
<% end %>
|
||||
|
||||
<%= render "shared/modals/login_modal" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "shared/modals/login_modal" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,5 +14,5 @@
|
||||
%>
|
||||
|
||||
<div class="btn-list text-right pt-8">
|
||||
<%= button_to t("verify.resend"), resend_email_path, params: { email_verified: false }, class: "btn btn-primary btn-space" %>
|
||||
<%= button_to t("verify.resend"), resend_email_path, params: { email: params['email'], email_verified: false }, class: "btn btn-primary btn-space" %>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user