Skip to content

Commit 5f9550e

Browse files
authored
add ability to preupload presentations (#409)
* add ability to preupload presentations * update gemfile.lock
1 parent 2f311cb commit 5f9550e

File tree

18 files changed

+319
-34
lines changed

18 files changed

+319
-34
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,5 @@ yarn-debug.log*
4646

4747
/vendor/bundle/
4848
/yarn.lock
49+
50+
.idea

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ group :test do
7777
end
7878

7979
group :production do
80+
gem 'google-cloud-storage', '~> 1.8', require: false
8081
end
8182

8283
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
@@ -110,3 +111,6 @@ gem 'logging', '~> 2.3'
110111
gem 'lograge', '~> 0.14.0'
111112
gem 'remote_syslog_logger'
112113
gem 'syslog'
114+
115+
# So we can upload files to Digital Ocean Spaces (S3-compatible)
116+
gem 'aws-sdk-s3', require: false

Gemfile.lock

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ GEM
7979
addressable (2.8.7)
8080
public_suffix (>= 2.0.2, < 7.0)
8181
ast (2.4.2)
82+
aws-eventstream (1.3.0)
83+
aws-partitions (1.1132.0)
84+
aws-sdk-core (3.227.0)
85+
aws-eventstream (~> 1, >= 1.3.0)
86+
aws-partitions (~> 1, >= 1.992.0)
87+
aws-sigv4 (~> 1.9)
88+
base64
89+
jmespath (~> 1, >= 1.6.1)
90+
logger
91+
aws-sdk-kms (1.94.0)
92+
aws-sdk-core (~> 3, >= 3.207.0)
93+
aws-sigv4 (~> 1.5)
94+
aws-sdk-s3 (1.167.0)
95+
aws-sdk-core (~> 3, >= 3.207.0)
96+
aws-sdk-kms (~> 1)
97+
aws-sigv4 (~> 1.5)
98+
aws-sigv4 (1.10.0)
99+
aws-eventstream (~> 1, >= 1.0.2)
82100
base64 (0.2.0)
83101
bigbluebutton-api-ruby (1.9.1)
84102
childprocess (>= 1.0.1)
@@ -119,7 +137,10 @@ GEM
119137
database_cleaner-core (~> 2.0.0)
120138
database_cleaner-core (2.0.1)
121139
date (3.4.1)
140+
declarative (0.0.20)
122141
diff-lcs (1.5.1)
142+
digest-crc (0.7.0)
143+
rake (>= 12.0.0, < 14.0.0)
123144
docile (1.4.1)
124145
domain_name (0.6.20240107)
125146
dotenv (3.1.6)
@@ -141,29 +162,69 @@ GEM
141162
logger
142163
faraday-net_http (3.4.0)
143164
net-http (>= 0.5.0)
144-
ffi (1.17.0)
145-
ffi (1.17.0-x86_64-linux-gnu)
165+
ffi (1.17.2-x86_64-linux-gnu)
166+
ffi (1.17.2-x86_64-linux-musl)
146167
globalid (1.2.1)
147168
activesupport (>= 6.1)
169+
google-apis-core (0.18.0)
170+
addressable (~> 2.5, >= 2.5.1)
171+
googleauth (~> 1.9)
172+
httpclient (>= 2.8.3, < 3.a)
173+
mini_mime (~> 1.0)
174+
mutex_m
175+
representable (~> 3.0)
176+
retriable (>= 2.0, < 4.a)
177+
google-apis-iamcredentials_v1 (0.24.0)
178+
google-apis-core (>= 0.15.0, < 2.a)
179+
google-apis-storage_v1 (0.54.0)
180+
google-apis-core (>= 0.15.0, < 2.a)
181+
google-cloud-core (1.8.0)
182+
google-cloud-env (>= 1.0, < 3.a)
183+
google-cloud-errors (~> 1.0)
184+
google-cloud-env (2.3.1)
185+
base64 (~> 0.2)
186+
faraday (>= 1.0, < 3.a)
187+
google-cloud-errors (1.5.0)
188+
google-cloud-storage (1.56.0)
189+
addressable (~> 2.8)
190+
digest-crc (~> 0.4)
191+
google-apis-core (~> 0.13)
192+
google-apis-iamcredentials_v1 (~> 0.18)
193+
google-apis-storage_v1 (>= 0.42)
194+
google-cloud-core (~> 1.6)
195+
googleauth (~> 1.9)
196+
mini_mime (~> 1.0)
197+
google-logging-utils (0.2.0)
198+
googleauth (1.14.0)
199+
faraday (>= 1.0, < 3.a)
200+
google-cloud-env (~> 2.2)
201+
google-logging-utils (~> 0.1)
202+
jwt (>= 1.4, < 3.0)
203+
multi_json (~> 1.11)
204+
os (>= 0.9, < 2.0)
205+
signet (>= 0.16, < 2.a)
148206
hashdiff (1.1.2)
149207
hashie (5.0.0)
150208
http-accept (1.7.0)
151209
http-cookie (1.0.8)
152210
domain_name (~> 0.5)
211+
httpclient (2.9.0)
212+
mutex_m
153213
i18n (1.14.6)
154214
concurrent-ruby (~> 1.0)
155215
jbuilder (2.13.0)
156216
actionview (>= 5.0.0)
157217
activesupport (>= 5.0.0)
158-
json (2.9.0)
218+
jmespath (1.6.2)
219+
json (2.13.2)
159220
jwt (2.9.3)
160221
base64
161222
language_server-protocol (3.17.0.3)
162223
listen (3.0.8)
163224
rb-fsevent (~> 0.9, >= 0.9.4)
164225
rb-inotify (~> 0.9, >= 0.9.7)
165226
little-plugger (1.1.4)
166-
logger (1.6.3)
227+
logger (1.7.0)
167228
logging (2.4.0)
168229
little-plugger (~> 1.1)
169230
multi_json (~> 1.14)
@@ -188,7 +249,6 @@ GEM
188249
mime-types-data (~> 3.2015)
189250
mime-types-data (3.2024.1203)
190251
mini_mime (1.1.5)
191-
mini_portile2 (2.8.8)
192252
minitest (5.25.4)
193253
multi_json (1.15.0)
194254
multi_xml (0.7.1)
@@ -207,10 +267,9 @@ GEM
207267
net-protocol
208268
netrc (0.11.0)
209269
nio4r (2.7.4)
210-
nokogiri (1.18.8)
211-
mini_portile2 (~> 2.8.2)
270+
nokogiri (1.18.9-x86_64-linux-gnu)
212271
racc (~> 1.4)
213-
nokogiri (1.18.8-x86_64-linux-gnu)
272+
nokogiri (1.18.9-x86_64-linux-musl)
214273
racc (~> 1.4)
215274
oauth2 (2.0.9)
216275
faraday (>= 0.17.3, < 3.0)
@@ -229,6 +288,7 @@ GEM
229288
omniauth-rails_csrf_protection (1.0.2)
230289
actionpack (>= 4.2)
231290
omniauth (~> 2.0)
291+
os (1.1.4)
232292
pagy (9.3.3)
233293
parallel (1.26.3)
234294
parser (3.3.6.0)
@@ -242,7 +302,7 @@ GEM
242302
puma (5.6.9)
243303
nio4r (~> 2.0)
244304
racc (1.8.1)
245-
rack (2.2.14)
305+
rack (2.2.17)
246306
rack-protection (3.2.0)
247307
base64 (>= 0.1.0)
248308
rack (~> 2.2, >= 2.2.4)
@@ -294,14 +354,19 @@ GEM
294354
remote_syslog_logger (1.0.4)
295355
syslog_protocol
296356
repost (0.4.2)
357+
representable (3.2.0)
358+
declarative (< 0.1.0)
359+
trailblazer-option (>= 0.1.1, < 0.2.0)
360+
uber (< 0.2.0)
297361
request_store (1.7.0)
298362
rack (>= 1.4)
299363
rest-client (2.1.0)
300364
http-accept (>= 1.7.0, < 2.0)
301365
http-cookie (>= 1.0.2, < 2.0)
302366
mime-types (>= 1.16, < 4.0)
303367
netrc (~> 0.8)
304-
rexml (3.4.0)
368+
retriable (3.1.2)
369+
rexml (3.4.1)
305370
rspec (3.13.0)
306371
rspec-core (~> 3.13.0)
307372
rspec-expectations (~> 3.13.0)
@@ -343,7 +408,7 @@ GEM
343408
rubocop (>= 1.52.0, < 2.0)
344409
rubocop-ast (>= 1.31.1, < 2.0)
345410
ruby-progressbar (1.13.0)
346-
rubyzip (2.3.2)
411+
rubyzip (2.4.1)
347412
sass-rails (6.0.0)
348413
sassc-rails (~> 2.1, >= 2.1.1)
349414
sassc (2.4.0)
@@ -361,6 +426,11 @@ GEM
361426
rubyzip (>= 1.2.2, < 3.0)
362427
websocket (~> 1.0)
363428
semantic_range (3.1.0)
429+
signet (0.20.0)
430+
addressable (~> 2.8)
431+
faraday (>= 0.17.5, < 3.a)
432+
jwt (>= 1.5, < 3.0)
433+
multi_json (~> 1.10)
364434
simplecov (0.22.0)
365435
docile (~> 1.1)
366436
simplecov-html (~> 0.11)
@@ -393,13 +463,15 @@ GEM
393463
tins (1.37.1)
394464
bigdecimal
395465
sync
466+
trailblazer-option (0.1.2)
396467
turbolinks (5.2.1)
397468
turbolinks-source (~> 5.2)
398469
turbolinks-source (5.2.0)
399470
tzinfo (2.0.6)
400471
concurrent-ruby (~> 1.0)
401472
tzinfo-data (1.2024.2)
402473
tzinfo (>= 1.0.0)
474+
uber (0.1.0)
403475
uglifier (4.2.1)
404476
execjs (>= 0.3.0, < 3)
405477
unicode-display_width (3.1.2)
@@ -436,12 +508,13 @@ GEM
436508
zeitwerk (2.6.18)
437509

438510
PLATFORMS
439-
ruby
440511
x86_64-linux
512+
x86_64-linux-musl
441513

442514
DEPENDENCIES
443515
action-cable-testing
444516
activerecord-session_store (>= 2.1.0)
517+
aws-sdk-s3
445518
bigbluebutton-api-ruby (~> 1.9.1)
446519
bigdecimal
447520
byebug
@@ -451,6 +524,7 @@ DEPENDENCIES
451524
dotenv-rails (>= 3.1.1)
452525
factory_bot_rails (>= 6.4.3)
453526
faker
527+
google-cloud-storage (~> 1.8)
454528
jbuilder (~> 2.11, >= 2.11.5)
455529
json
456530
listen (>= 3.0.5, < 3.2)

app/controllers/concerns/bbb_helper.rb

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def bbb
3232
@bbb_credentials ||= initialize_bbb_credentials
3333
bbb_url = remove_slash(@bbb_credentials.endpoint(@chosen_room.tenant))
3434
bbb_secret = @bbb_credentials.secret(@chosen_room.tenant)
35-
BigBlueButton::BigBlueButtonApi.new(bbb_url, bbb_secret, '1.0', Rails.logger)
35+
BigBlueButton::BigBlueButtonApi.new(bbb_url, bbb_secret, '1.8', Rails.logger)
3636
rescue StandardError => e
3737
logger.error("Error in creating BBB object: #{e}")
3838
raise RoomsError::CustomError.new(code: 500, message: 'There was an error initializing BigBlueButton credentials', key: 'BigBlueButton Error')
@@ -90,8 +90,23 @@ def create_meeting
9090
add_ext_params('create', create_options)
9191
logger.debug("[BbbHelper] create_options for room #{@chosen_room.id}: #{create_options}")
9292

93-
# Send the create request.
94-
bbb.create_meeting(@chosen_room.name, @chosen_room.handler, create_options)
93+
begin
94+
if @chosen_room.presentation.attached?
95+
modules = BigBlueButton::BigBlueButtonModules.new
96+
url = rails_blob_url(@chosen_room.presentation).gsub('&', '%26')
97+
name = @chosen_room.presentation.filename
98+
logger.info("Support: Room #{@chosen_room.id} starting using presentation #{name}: #{url}")
99+
modules.add_presentation(:url, url, name)
100+
# Send the create request.
101+
bbb.create_meeting(@chosen_room.name, @chosen_room.handler, create_options, modules)
102+
else
103+
# Send the create request.
104+
bbb.create_meeting(@chosen_room.name, @chosen_room.handler, create_options)
105+
end
106+
rescue BigBlueButton::BigBlueButtonException => e
107+
Rails.logger.error("BigBlueButton failed on create: #{e.key}: #{e.message}")
108+
raise e
109+
end
95110
end
96111

97112
# Perform ends meeting for the current room.

app/controllers/rooms_controller.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,25 @@ def update
118118
end
119119
end
120120

121+
def remove_presentation
122+
begin
123+
@room.presentation.purge
124+
125+
flash[:success] = "I18n.t('room.preupload_remove_success')"
126+
rescue StandardError => e
127+
logger.error("Support: Error in removing room presentation: #{e}")
128+
flash[:alert] = "I18n.t('room.preupload_remove_error')"
129+
end
130+
131+
redirect_back(fallback_location: room_path(@room))
132+
end
133+
134+
# Returns a list of allowed file types
135+
def allowed_file_types
136+
Rails.configuration.allowed_file_types
137+
end
138+
helper_method :allowed_file_types
139+
121140
# DELETE /rooms/1
122141
# DELETE /rooms/1.json
123142
def destroy
@@ -264,6 +283,12 @@ def revoke_shared_code
264283

265284
private
266285

286+
# Checks if the file extension is allowed
287+
def valid_file_type
288+
Rails.configuration.allowed_file_types.split(',')
289+
.include?(File.extname(room_params[:presentation].original_filename.downcase))
290+
end
291+
267292
def set_error(error, status, domain = 'room')
268293
@room = @user = nil
269294
@error = {
@@ -413,6 +438,7 @@ def room_params
413438
:code,
414439
:shared_code,
415440
:use_shared_code,
441+
:presentation,
416442
settings: Room.stored_attributes[:settings]
417443
)
418444
end

app/models/room.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
class Room < ApplicationRecord
1919
include BrokerHelper
2020

21+
has_one_attached :presentation
22+
2123
before_save :default_values
2224

2325
store_accessor :settings, %i[lockSettingsDisableCam lockSettingsDisableMic lockSettingsDisablePrivateChat lockSettingsDisablePublicChat lockSettingsDisableNote]

app/views/rooms/_form.html.erb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,37 @@
7070
<%= form.hidden_field :moderator, value: @room.moderator %>
7171
<%= form.hidden_field :viewer, value: @room.viewer %>
7272

73+
<!-- Pre-upload Presentation -->
74+
<details>
75+
<summary class="text-black"><%= t('default.room.settings.preuploadPresentation') %>
76+
<%= image_tag('lock.svg', width: '15', height: '15', alt: 'lock', class: 'lock-icon-placement lock-visibility', title: 'Disabled because "Use Shared Code" is enabled') %>
77+
</summary>
78+
79+
<% if @room.presentation.attached? %>
80+
<div class="block p-6 w-full border border-gray-200 rounded-lg shadow-md bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
81+
<span><b><%= t('default.room.preupload.current') %>: </b></span>
82+
<%= link_to "#{@room.presentation.filename}", rails_blob_url(@room.presentation, disposition: 'attachment'), target: '_blank', class: 'hover:bg-transparent hover:text-bbb-blue' %>
83+
<%= link_to remove_presentation_path(@room, :launch_nonce => @launch_nonce), method: :post, class: "px-4 py-3 font-sans text-xl hover:bg-transparent check-disabled" do %>
84+
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 hover:stroke-bbb-blue" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
85+
<path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
86+
</svg>
87+
<% end %>
88+
</div>
89+
<% else %>
90+
<div class="mb-5">
91+
<label for="presentation_upload" class="flex w-full items-center text-sm border border-gray-300 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 text-left overflow-hidden">
92+
<span class=" text-white px-4 py-3 flex-shrink-0 w-36 text-center bg-blue-950 hover:bg-blue-950/80">
93+
Upload File
94+
</span>
95+
<%= form.file_field :presentation, id: 'presentation_upload', class: "w-full text-gray-500 truncate", accept: allowed_file_types %>
96+
</label>
97+
</div>
98+
<% end %>
99+
100+
</details>
101+
102+
<hr>
103+
73104
<% @lockSettings = @room.settings.select { |key, value| key.start_with?("lock")} %>
74105
<% @recordingSettings = @room.settings.select { |key, value| Room::RECORDING_SETTINGS.include?(key.to_sym)} %>
75106
<% @roomSettings = @room.settings.select { |key, value| Room::ROOM_SETTINGS.include?(key.to_sym)} %>

config/application.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,9 @@ class Application < Rails::Application
7878
config.handler_legacy_api_enabled = (config.handler_legacy_api_endpoint && config.handler_legacy_api_secret)
7979

8080
config.handler_legacy_new_room_enabled = ENV.fetch('HANDLER_LEGACY_NEW_ROOM_ENABLED', 'true').casecmp?('true')
81+
82+
# File types allowed in preupload presentation
83+
config.allowed_file_types = '.doc,.docx,.ppt,.pptx,.pdf,.xls,.xlsx,.txt,.rtf,.odt,.ods,.odp,.odg,.odc,.odi,.jpg,.jpeg,.png'
84+
config.active_storage.routes_prefix = '/rooms/rails/active_storage'
8185
end
8286
end

config/environments/development.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
config.action_controller.perform_caching = true
5050

5151
# Store uploaded files on the local file system (see config/storage.yml for options)
52-
config.active_storage.service = :local
52+
config.active_storage.service = ENV.fetch('CLOUD_PROVIDER', 'local').downcase.to_sym
5353

5454
# Don't care if the mailer can't send.
5555
config.action_mailer.raise_delivery_errors = false

0 commit comments

Comments
 (0)