Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LTI-393: Refactor cache, extra param logic #346

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions app/controllers/concerns/bbb_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ def meeting_running?

# Fetches all recordings for a room.
def recordings
res = Rails.cache.fetch("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}", expires_in: Rails.configuration.cache_expires_in_minutes.minutes) if Rails.configuration.cache_enabled
res ||= bbb.get_recordings(meetingID: @chosen_room.handler)
res = CacheService.fetch_or_compute("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}") { bbb.get_recordings(meetingID: @chosen_room.handler) }
recordings_formatted(res)
end

Expand Down Expand Up @@ -161,29 +160,33 @@ def server_running?

# Deletes a recording.
def delete_recording(record_id)
Rails.cache.delete("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}") if Rails.configuration.cache_enabled
delete_recording_cache
bbb.delete_recordings(record_id)
end

# Publishes a recording.
def publish_recording(record_id)
Rails.cache.delete("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}") if Rails.configuration.cache_enabled
delete_recording_cache
bbb.publish_recordings(record_id, true)
end

# Unpublishes a recording.
def unpublish_recording(record_id)
Rails.cache.delete("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}") if Rails.configuration.cache_enabled
delete_recording_cache
bbb.publish_recordings(record_id, false)
end

# Updates a recording.
def update_recording(record_id, meta)
Rails.cache.delete("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}") if Rails.configuration.cache_enabled
delete_recording_cache
meta[:recordID] = record_id
bbb.send_api_request('updateRecordings', meta)
end

def delete_recording_cache
CacheService.delete("rooms/#{@chosen_room.handler}/#{RECORDINGS_KEY}")
end

# Return the number of participants in a meeting for the current room.
def participant_count
info = meeting_info
Expand Down Expand Up @@ -246,8 +249,6 @@ def initialize_bbb_credentials
bbb_credentials = Bbb::Credentials.new(Rails.configuration.bigbluebutton_endpoint, Rails.configuration.bigbluebutton_secret)
bbb_credentials.multitenant_api_endpoint = Rails.configuration.external_multitenant_endpoint
bbb_credentials.multitenant_api_secret = Rails.configuration.external_multitenant_secret
bbb_credentials.cache = Rails.cache
bbb_credentials.cache_enabled = Rails.configuration.cache_enabled
bbb_credentials
end

Expand Down
3 changes: 1 addition & 2 deletions app/controllers/concerns/broker_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ module BrokerHelper

# Fetch tenant object from the broker
def broker_tenant_info(tenant)
# tenant ||= @room&.tenant || ''
Rails.cache.fetch("rooms/tenant/#{tenant}", expires_in: Rails.configuration.cache_expires_in_minutes.minutes) do
CacheService.fetch_or_compute("rooms/tenant/#{tenant}") do
bbbltibroker_url = omniauth_bbbltibroker_url("/api/v1/tenants/#{tenant}")
get_response = RestClient.get(bbbltibroker_url, 'Authorization' => "Bearer #{omniauth_client_token(omniauth_bbbltibroker_url)}")

Expand Down
50 changes: 50 additions & 0 deletions app/controllers/concerns/extra_params_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

#
## BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
#

module ExtraParamsHelper
extend ActiveSupport::Concern

# return a hash of key:value pairs from the launch_params,
# for keys that exist in the extra params hash retrieved from the broker settings
def launch_and_extra_params_intersection_hash(launch_params, action, actions_hash)
CacheService.fetch_or_compute("rooms/#{@chosen_room.handler}/tenant/#{@chosen_room.tenant}/user/#{@user.uid}/ext_#{action}_params") { calculate_intersection_hash(launch_params, actions_hash) }
end

def calculate_intersection_hash(launch_params, actions_hash)
result = {}
actions_hash&.each_key do |key|
value = find_launch_param(launch_params, key)
result[key] = value if value
end
result
end

# Check if the launch params contain a certain param
# If they do, return the value of that param
def find_launch_param(launch_params, key)
return launch_params[key] if launch_params.key?(key)

launch_params.each_value do |value|
if value.is_a?(Hash)
result = find_launch_param(value, key)
return result if result
end
end

nil
end
end
50 changes: 4 additions & 46 deletions app/controllers/rooms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class RoomsController < ApplicationController
include BbbHelper
include OmniauthHelper
include BrokerHelper
include ExtraParamsHelper

before_action :print_parameters if Rails.configuration.developer_mode_enabled
before_action :authenticate_user!, except: %i[meeting_close], raise: false
Expand Down Expand Up @@ -510,15 +511,9 @@ def set_ext_params
tenant = @chosen_room.tenant
@broker_ext_params ||= tenant_setting(tenant, 'ext_params')

launch_params = if Rails.configuration.cache_enabled
Rails.cache.fetch("rooms/#{@chosen_room.handler}/tenant/#{tenant}/user/#{@user.uid}/launch_params",
expires_in: Rails.configuration.cache_expires_in_minutes.minutes) do
logger.debug('fetching launch params for extra params from cache')
launch_request_params['message']
end
else
launch_request_params['message']
end
launch_params = CacheService.fetch_or_compute("rooms/#{@chosen_room.handler}/tenant/#{tenant}/user/#{@user.uid}/launch_params") do
launch_request_params['message']
end

logger.debug("[Rooms Controller] extra params from broker for room #{@chosen_room.name}: #{@broker_ext_params}")

Expand All @@ -531,41 +526,4 @@ def set_ext_params
rescue StandardError => e
logger.error("[Rooms Controller] Error setting extra parameters: #{e}")
end

# return a hash of key:value pairs from the launch_params,
# for keys that exist in the extra params hash retrieved from the broker settings
def launch_and_extra_params_intersection_hash(launch_params, action, actions_hash)
if Rails.configuration.cache_enabled
Rails.cache.fetch("rooms/#{@chosen_room.handler}/tenant/#{@chosen_room.tenant}/user/#{@user.uid}/ext_#{action}_params",
expires_in: Rails.configuration.cache_expires_in_minutes.minutes) do
calculate_intersection_hash(launch_params, actions_hash)
end
else
calculate_intersection_hash(launch_params, actions_hash)
end
end

def calculate_intersection_hash(launch_params, actions_hash)
result = {}
actions_hash&.each_key do |key|
value = find_launch_param(launch_params, key)
result[key] = value if value
end
result
end

# Check if the launch params contain a certain param
# If they do, return the value of that param
def find_launch_param(launch_params, key)
return launch_params[key] if launch_params.key?(key)

launch_params.each_value do |value|
if value.is_a?(Hash)
result = find_launch_param(value, key)
return result unless result.nil?
end
end

nil
end
end
29 changes: 29 additions & 0 deletions app/services/cache_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

class CacheService
def self.fetch_or_compute(cache_key, expiration = Rails.configuration.cache_expires_in_minutes.minutes, &block)
if Rails.configuration.cache_enabled
Rails.logger.debug("[CacheService] Cache enabled, attempt to fetch cache for the following key: #{cache_key}")
Rails.cache.fetch(cache_key, expires_in: expiration, &block)
else
yield
end
end

def self.delete(cache_key)
Rails.cache.delete(cache_key) if Rails.configuration.cache_enabled
end
end
71 changes: 32 additions & 39 deletions lib/bbb/credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ class Credentials
include OmniauthHelper
include BrokerHelper

attr_writer :cache, :cache_enabled, :multitenant_api_endpoint, :multitenant_api_secret # Rails.cache store is assumed. # Enabled by default.
attr_writer :multitenant_api_endpoint, :multitenant_api_secret

def initialize(endpoint, secret)
# Set default credentials.
@endpoint = endpoint
@secret = secret
@multitenant_api_endpoint = nil
@multitenant_api_secret = nil
@cache_enabled = true
end

def endpoint(tenant)
Expand Down Expand Up @@ -62,54 +61,48 @@ def tenant_info(tenant, key)
end

def formatted_tenant_info(tenant)
if @cache_enabled
Rails.logger.debug('Cache enabled, attempt to fetch credentials from cache...')
cached_tenant = @cache.fetch("rooms/#{tenant}/tenantInfo", expires_in: Rails.configuration.cache_expires_in_minutes.minutes)
return cached_tenant unless cached_tenant.nil?
end

# Get tenant info from broker
Rails.logger.debug('No cache. Attempt to fetch credentials from broker...')
tenant_info = broker_tenant_info(tenant)
CacheService.fetch_or_compute("rooms/#{tenant}/tenantInfo") do
# Get tenant info from broker
Rails.logger.debug('No cache. Attempt to fetch credentials from broker...')
tenant_info = broker_tenant_info(tenant)

# Get tenant credentials from TENANT_CREDENTIALS environment variable
tenant_credentials = JSON.parse(Rails.configuration.tenant_credentials)[tenant]
# Get tenant credentials from TENANT_CREDENTIALS environment variable
tenant_credentials = JSON.parse(Rails.configuration.tenant_credentials)[tenant]

raise 'Tenant does not exist' if tenant_info.nil? && tenant_credentials.nil? && tenant.present?
raise 'Tenant does not exist' if tenant_info.nil? && tenant_credentials.nil? && tenant.present?

# use credentials from broker first, if not found then use env variable, and then use bbb_endpoint & bbb_secret if single tenant
tenant_settings = tenant_info&.[]('settings')
# use credentials from broker first, if not found then use env variable, and then use bbb_endpoint & bbb_secret if single tenant
tenant_settings = tenant_info&.[]('settings')

api_url = tenant_settings&.[]('bigbluebutton_url') ||
tenant_credentials&.[]('bigbluebutton_url') ||
(@endpoint if tenant.blank?)
api_url = tenant_settings&.[]('bigbluebutton_url') ||
tenant_credentials&.[]('bigbluebutton_url') ||
(@endpoint if tenant.blank?)

secret = tenant_settings&.[]('bigbluebutton_secret') ||
tenant_credentials&.[]('bigbluebutton_secret') ||
(@secret if tenant.blank?)
secret = tenant_settings&.[]('bigbluebutton_secret') ||
tenant_credentials&.[]('bigbluebutton_secret') ||
(@secret if tenant.blank?)

missing_creds = !(api_url && secret)
missing_creds = !(api_url && secret)

raise 'Bigbluebutton credentials not found' if tenant.blank? && missing_creds
raise 'Bigbluebutton credentials not found' if tenant.blank? && missing_creds

raise 'Multitenant API not defined' if tenant.present? && missing_creds && (@multitenant_api_endpoint.nil? || @multitenant_api_secret.nil?)
raise 'Multitenant API not defined' if tenant.present? && missing_creds && (@multitenant_api_endpoint.nil? || @multitenant_api_secret.nil?)

# get the api URL and secret from the LB if not defined in tenant settings
if missing_creds
Rails.logger.debug('Missing credentials, attempt to fetch from multitenant_api_endpoint...')
# Build the URI.
uri = encoded_url(
"#{@multitenant_api_endpoint}api/getUser",
@multitenant_api_secret,
{ name: tenant }
)
# get the api URL and secret from the LB if not defined in tenant settings
if missing_creds
Rails.logger.debug('Missing credentials, attempt to fetch from multitenant_api_endpoint...')
# Build the URI.
uri = encoded_url(
"#{@multitenant_api_endpoint}api/getUser",
@multitenant_api_secret,
{ name: tenant }
)

http_response = http_request(uri)
response = parse_response(http_response)
response['settings'] = tenant_settings
end
http_response = http_request(uri)
response = parse_response(http_response)
response['settings'] = tenant_settings
end

@cache.fetch("rooms/#{tenant}/tenantInfo", expires_in: Rails.configuration.cache_expires_in_minutes.minutes) do
response || { 'apiURL' => api_url, 'secret' => secret, 'settings' => tenant_settings }
end
end
Expand Down