diff --git a/app/controllers/api/v1/meetings_controller.rb b/app/controllers/api/v1/meetings_controller.rb index ef823e0705ac12c8875c64b795d0fa189155b4bb..3b5126fac55eb43fd4c5691d6a348abe84bb66d9 100644 --- a/app/controllers/api/v1/meetings_controller.rb +++ b/app/controllers/api/v1/meetings_controller.rb @@ -29,7 +29,7 @@ module Api # Starts a BigBlueButton meetings and joins in the meeting starter def start begin - MeetingStarter.new(room: @room, base_url: root_url, current_user:, provider: current_provider).call + MeetingStarter.new(room: @room, base_url: request.base_url, current_user:, provider: current_provider).call rescue BigBlueButton::BigBlueButtonException => e return render_error status: :bad_request unless e.key == 'idNotUnique' end @@ -68,7 +68,7 @@ module Api if !data[:status] && settings['glAnyoneCanStart'] == 'true' # Meeting isnt running and anyoneCanStart setting is enabled begin - MeetingStarter.new(room: @room, base_url: root_url, current_user:, provider: current_provider).call + MeetingStarter.new(room: @room, base_url: request.base_url, current_user:, provider: current_provider).call rescue BigBlueButton::BigBlueButtonException => e return render_error status: :bad_request unless e.key == 'idNotUnique' end diff --git a/app/controllers/api/v1/site_settings_controller.rb b/app/controllers/api/v1/site_settings_controller.rb index 8bf06d0d5f88d99a6547797747b802b4ac67ba75..ecbd9472841b6c11d76908b10507a92b1738448b 100644 --- a/app/controllers/api/v1/site_settings_controller.rb +++ b/app/controllers/api/v1/site_settings_controller.rb @@ -25,17 +25,9 @@ module Api # GET /api/v1/site_settings # Returns the values of 1 or multiple site_settings that are not forbidden to access def index - settings = {} return render_error status: :forbidden if forbidden_settings(params[:names]) - if params[:names].is_a?(Array) - params[:names].each do |name| - settings[name] = SettingGetter.new(setting_name: name, provider: current_provider).call - end - else - # return the value directly - settings = SettingGetter.new(setting_name: params[:names], provider: current_provider).call - end + settings = SettingGetter.new(setting_name: params[:names], provider: current_provider).call render_data data: settings, status: :ok end diff --git a/app/javascript/channels/consumer.jsx b/app/javascript/channels/consumer.jsx index 99123c203e60384c772ba2ff53c692c47d2c6129..e1d523c541e515489274ffb3ded92673eacd645e 100644 --- a/app/javascript/channels/consumer.jsx +++ b/app/javascript/channels/consumer.jsx @@ -19,4 +19,4 @@ import { createConsumer } from '@rails/actioncable'; -export default createConsumer(); +export default createConsumer(`${process.env.RELATIVE_URL_ROOT}/cable`); diff --git a/app/javascript/hooks/queries/users/useUser.jsx b/app/javascript/hooks/queries/users/useUser.jsx index 64f22960a1a74d411ffc12f1d2cd2c332f0b4c8c..54c460bb6ec045bc3e940aef348518c726edee4c 100644 --- a/app/javascript/hooks/queries/users/useUser.jsx +++ b/app/javascript/hooks/queries/users/useUser.jsx @@ -15,11 +15,11 @@ // with Greenlight; if not, see <http://www.gnu.org/licenses/>. import { useQuery } from 'react-query'; -import axios from 'axios'; +import axios from '../../../helpers/Axios'; export default function useUser(userId) { return useQuery( ['getUser', userId], - () => axios.get(`/api/v1/users/${userId}.json`).then((resp) => resp.data.data), + () => axios.get(`/users/${userId}.json`).then((resp) => resp.data.data), ); } diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 2df77808caf637c086904fcfe6aaed0ded5c98e8..3e00b6fc0288fe6ea5a4d617adc4235c478006c4 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -55,8 +55,7 @@ class UserMailer < ApplicationMailer end def branding - branding_hash = SiteSetting.includes(:setting).where(provider: @provider, settings: { name: %w[PrimaryColor BrandingImage] }) - .pluck(:name, :value).to_h + branding_hash = SettingGetter.new(setting_name: %w[PrimaryColor BrandingImage], provider: @provider).call @brand_image = ActionController::Base.helpers.image_url(branding_hash['BrandingImage'], host: @base_url) @brand_color = branding_hash['PrimaryColor'] end diff --git a/app/services/meeting_starter.rb b/app/services/meeting_starter.rb index e576082c42815a9fb71cb425a65b736da194fa6b..4575aef490104541fb1ba2d999907a2182748224 100644 --- a/app/services/meeting_starter.rb +++ b/app/services/meeting_starter.rb @@ -56,7 +56,7 @@ class MeetingStarter private def computed_options(access_code:) - room_url = File.join(@base_url, '/rooms/', @room.friendly_id, '/join') + room_url = "#{root_url(host: @base_url)}rooms/#{@room.friendly_id}/join" moderator_message = "#{I18n.t('meeting.moderator_message')}<br>#{room_url}" moderator_message += "<br>#{I18n.t('meeting.access_code', code: access_code)}" if access_code.present? { diff --git a/app/services/setting_getter.rb b/app/services/setting_getter.rb index 4c5f435279c069c0cbac6661268756efd4d2c389..fda7f838d17ed18aad8186b2d9e6192cb9b069af 100644 --- a/app/services/setting_getter.rb +++ b/app/services/setting_getter.rb @@ -20,40 +20,51 @@ class SettingGetter include Rails.application.routes.url_helpers def initialize(setting_name:, provider:) - @setting_name = setting_name + @setting_name = Array(setting_name) @provider = provider end def call - setting = SiteSetting.joins(:setting) - .find_by( - provider: @provider, - setting: { name: @setting_name } - ) - - value = if @setting_name == 'BrandingImage' - if setting.image.attached? - rails_blob_path setting.image, only_path: true - else - ActionController::Base.helpers.image_path('bbb_logo.png') - end - else - setting&.value - end - - transform_value(value) + # Fetch the site settings records while eager loading their respective settings ↓ + site_settings = SiteSetting.includes(:setting) + .where( + provider: @provider, + setting: { name: @setting_name } + ) + + # Pessimist check: Pass only if all provided names were found ↓ + return nil unless @setting_name.size == site_settings.size + + site_settings_hash = {} + + # In memory prepare the result hash ↓ + site_settings.map do |site_setting| + site_settings_hash[site_setting.setting.name] = transform_value(site_setting) + end + + # If there's only one setting is being fetched no need for a hash ↓ + return site_settings_hash.values.first if site_settings_hash.size == 1 + + # A Hash<setting_name => parsed_value> is returned otherwise ↓ + site_settings_hash end private - def transform_value(value) - case value + def transform_value(site_setting) + if site_setting.setting.name == 'BrandingImage' + return rails_blob_path site_setting.image, only_path: true if site_setting.image.attached? + + return ActionController::Base.helpers.image_path('bbb_logo.png') + end + + case site_setting.value when 'true' true when 'false' false else - value + site_setting.value end end end diff --git a/config/application.rb b/config/application.rb index 3c50cf78dd0e35bf58af3f2cf6287965d153861d..71810992cd800f9f8f6fa70ccf98ed2b407594fb 100644 --- a/config/application.rb +++ b/config/application.rb @@ -66,6 +66,8 @@ module Greenlight config.bigbluebutton_secret = ENV.fetch('BIGBLUEBUTTON_SECRET', '8cd8ef52e8e101574e400365b55e11a6') - config.relative_url_root = ENV.fetch('RELATIVE_URL_ROOT', '/') + # Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes. + config.relative_url_root = ENV.fetch('RELATIVE_URL_ROOT', nil)&.sub(%r{/*\z}, '') + config.relative_url_root = '/' if config.relative_url_root.blank? end end diff --git a/esbuild.dev.mjs b/esbuild.dev.mjs index fb48838beefd311402906e954b0f88d8fc68e767..83a11e9c472b876c4856a566910efa56fee0ad75 100644 --- a/esbuild.dev.mjs +++ b/esbuild.dev.mjs @@ -1,6 +1,7 @@ import * as esbuild from 'esbuild'; -const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/$/, ''); +// Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes. +const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/*$/, ''); await esbuild.build({ entryPoints: ['app/javascript/main.jsx'], diff --git a/esbuild.mjs b/esbuild.mjs index 7b76ffbfb799e8e9fa693ba2b66eb7392dd5a5cb..8a6589592045c2b7c5d8eb351b7d93bc2e83f5ba 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -1,6 +1,7 @@ import * as esbuild from 'esbuild'; -const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/$/, ''); +// Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes. +const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/*$/, ''); await esbuild.build({ entryPoints: ['app/javascript/main.jsx'], diff --git a/spec/controllers/meetings_controller_spec.rb b/spec/controllers/meetings_controller_spec.rb index 66827d384e74abbe173e07f5e55f44e29fa55958..21230bb1246bb58557c403d9154524308e7c69a6 100644 --- a/spec/controllers/meetings_controller_spec.rb +++ b/spec/controllers/meetings_controller_spec.rb @@ -41,7 +41,7 @@ RSpec.describe Api::V1::MeetingsController, type: :controller do describe '#start' do it 'makes a call to the MeetingStarter service with the right values and returns the join url' do - expect(MeetingStarter).to receive(:new).with(room:, base_url: root_url, current_user: user, provider: 'greenlight').and_call_original + expect(MeetingStarter).to receive(:new).with(room:, base_url: request.base_url, current_user: user, provider: 'greenlight').and_call_original expect_any_instance_of(MeetingStarter).to receive(:call) expect_any_instance_of(BigBlueButtonApi).to receive(:join_meeting).with(room:, name: user.name, avatar_url: nil, role: 'Moderator') @@ -343,7 +343,7 @@ RSpec.describe Api::V1::MeetingsController, type: :controller do allow_any_instance_of(BigBlueButtonApi).to receive(:meeting_running?).and_return(false) - expect(MeetingStarter).to receive(:new).with(room:, base_url: root_url, current_user: user, provider: 'greenlight').and_call_original + expect(MeetingStarter).to receive(:new).with(room:, base_url: request.base_url, current_user: user, provider: 'greenlight').and_call_original expect_any_instance_of(MeetingStarter).to receive(:call) post :status, params: { friendly_id: room.friendly_id, name: user.name } diff --git a/spec/controllers/site_settings_controller_spec.rb b/spec/controllers/site_settings_controller_spec.rb index f049573d126deac4fc50d27bd83712fd88a22de5..8b2faf14692df01d95c14be9013269ba16de9a10 100644 --- a/spec/controllers/site_settings_controller_spec.rb +++ b/spec/controllers/site_settings_controller_spec.rb @@ -38,15 +38,13 @@ RSpec.describe Api::V1::SiteSettingsController, type: :controller do end it 'calls SettingGetter and returns multiple values' do - expect(SettingGetter).to receive(:new).with(setting_name: 'SettingName', provider: 'greenlight').and_call_original - expect(SettingGetter).to receive(:new).with(setting_name: 'SettingName2', provider: 'greenlight').and_call_original - allow_any_instance_of(SettingGetter).to receive(:call).and_return('false') + expect(SettingGetter).to receive(:new).with(setting_name: %w[Uno Dos Tres], provider: 'greenlight').and_call_original + allow_any_instance_of(SettingGetter).to receive(:call).and_return({ 'Uno' => 1, 'Dos' => 2, 'Tres' => 3 }) - get :index, params: { names: %w[SettingName SettingName2] } + get :index, params: { names: %w[Uno Dos Tres] } expect(response).to have_http_status(:ok) - expect(JSON.parse(response.body)['data']['SettingName']).to eq('false') - expect(JSON.parse(response.body)['data']['SettingName2']).to eq('false') + expect(JSON.parse(response.body)['data']).to eq({ 'Uno' => 1, 'Dos' => 2, 'Tres' => 3 }) end it 'returns forbidden if trying to access a forbidden setting' do