bigbluebutton_rails 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/CHANGELOG.md +34 -0
  4. data/Dockerfile +23 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +14 -5
  7. data/README.md +42 -59
  8. data/Rakefile +6 -3
  9. data/app/controllers/bigbluebutton/api/rooms_controller.rb +117 -0
  10. data/app/controllers/bigbluebutton/playback_types_controller.rb +0 -3
  11. data/app/controllers/bigbluebutton/recordings_controller.rb +37 -23
  12. data/app/controllers/bigbluebutton/rooms_controller.rb +6 -31
  13. data/app/controllers/bigbluebutton/servers_controller.rb +0 -14
  14. data/app/helpers/bigbluebutton_rails_helper.rb +4 -0
  15. data/app/models/bigbluebutton_attendee.rb +21 -0
  16. data/app/models/bigbluebutton_meeting.rb +5 -0
  17. data/app/models/bigbluebutton_playback_format.rb +3 -2
  18. data/app/models/bigbluebutton_recording.rb +164 -68
  19. data/app/models/bigbluebutton_room.rb +148 -59
  20. data/app/models/bigbluebutton_server.rb +1 -1
  21. data/app/views/bigbluebutton/api/error.rabl +10 -0
  22. data/app/views/bigbluebutton/api/rooms/index.rabl +45 -0
  23. data/app/views/bigbluebutton/api/rooms/join.rabl +6 -0
  24. data/app/views/bigbluebutton/api/rooms/running.rabl +10 -0
  25. data/app/views/bigbluebutton/recordings/play.html.erb +1 -0
  26. data/app/views/bigbluebutton/servers/_activity_list.html.erb +5 -5
  27. data/app/workers/{bigbluebutton_finish_meetings.rb → bigbluebutton_finish_meetings_worker.rb} +2 -2
  28. data/app/workers/{bigbluebutton_meeting_updater.rb → bigbluebutton_meeting_updater_worker.rb} +3 -3
  29. data/app/workers/bigbluebutton_recordings_for_room_worker.rb +27 -0
  30. data/app/workers/{bigbluebutton_update_recordings.rb → bigbluebutton_update_recordings_worker.rb} +2 -2
  31. data/app/workers/{bigbluebutton_update_server_configs.rb → bigbluebutton_update_server_configs_worker.rb} +3 -3
  32. data/bigbluebutton_rails.gemspec +1 -0
  33. data/config/locales/en.yml +21 -0
  34. data/config/locales/pt-br.yml +1 -0
  35. data/config/resque/resque.rake +7 -1
  36. data/config/resque/workers_schedule.yml +3 -3
  37. data/docker-compose.yml +68 -0
  38. data/dumb-init_1.2.0 +0 -0
  39. data/lib/bigbluebutton_rails.rb +1 -2
  40. data/lib/bigbluebutton_rails/api_controller_methods.rb +138 -0
  41. data/lib/bigbluebutton_rails/configuration.rb +33 -4
  42. data/lib/bigbluebutton_rails/controller_methods.rb +0 -31
  43. data/lib/bigbluebutton_rails/exceptions.rb +17 -0
  44. data/lib/bigbluebutton_rails/rails/routes.rb +14 -0
  45. data/lib/bigbluebutton_rails/version.rb +1 -1
  46. data/lib/generators/bigbluebutton_rails/templates/migration.rb +17 -3
  47. data/lib/generators/bigbluebutton_rails/templates/migration_2_2_0.rb +1 -1
  48. data/lib/generators/bigbluebutton_rails/templates/migration_2_2_0_b.rb +106 -0
  49. data/lib/generators/bigbluebutton_rails/templates/migration_2_3_0.rb +22 -0
  50. data/lib/tasks/bigbluebutton_rails/meetings.rake +1 -1
  51. data/spec/controllers/bigbluebutton/api/rooms_controller_spec.rb +498 -0
  52. data/spec/controllers/bigbluebutton/recordings_controller_spec.rb +84 -0
  53. data/spec/controllers/bigbluebutton/rooms_controller_exception_handling_spec.rb +2 -2
  54. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +24 -22
  55. data/spec/controllers/bigbluebutton/servers_controller_spec.rb +9 -0
  56. data/spec/factories/bigbluebutton_attendee.rb +7 -0
  57. data/spec/factories/bigbluebutton_meeting.rb +0 -1
  58. data/spec/factories/bigbluebutton_playback_type.rb +1 -0
  59. data/spec/factories/bigbluebutton_recording.rb +2 -4
  60. data/spec/helpers/bigbluebutton_rails_helper_spec.rb +10 -2
  61. data/spec/lib/bigbluebutton_rails/background_tasks_spec.rb +1 -0
  62. data/spec/lib/tasks/meetings_rake_spec.rb +1 -1
  63. data/spec/models/bigbluebutton_attendee_spec.rb +44 -0
  64. data/spec/models/bigbluebutton_meeting_db_spec.rb +0 -1
  65. data/spec/models/bigbluebutton_meeting_spec.rb +1 -0
  66. data/spec/models/bigbluebutton_playback_format_spec.rb +2 -0
  67. data/spec/models/bigbluebutton_playback_type_db_spec.rb +1 -0
  68. data/spec/models/bigbluebutton_recording_db_spec.rb +2 -2
  69. data/spec/models/bigbluebutton_recording_spec.rb +404 -72
  70. data/spec/models/bigbluebutton_room_spec.rb +435 -148
  71. data/spec/rails_app/config/database.yml.example +10 -11
  72. data/spec/rails_app/config/initializers/resque.rb +33 -0
  73. data/spec/rails_app/config/routes.rb +2 -0
  74. data/spec/rails_app/lib/tasks/db/populate.rake +73 -55
  75. data/spec/support/mocked_server.rb +1 -1
  76. data/spec/workers/{bigbluebutton_finish_meetings_spec.rb → bigbluebutton_finish_meetings_worker_spec.rb} +3 -3
  77. data/spec/workers/{bigbluebutton_meeting_updater_spec.rb → bigbluebutton_meeting_updater_worker_spec.rb} +8 -7
  78. data/spec/workers/bigbluebutton_recordings_for_room_worker_spec.rb +49 -0
  79. data/spec/workers/{bigbluebutton_update_recordings_spec.rb → bigbluebutton_update_recordings_worker_spec.rb} +3 -3
  80. data/spec/workers/{bigbluebutton_update_server_configs_spec.rb → bigbluebutton_update_server_configs_worker_spec.rb} +4 -4
  81. metadata +42 -14
  82. data/lib/classes/bigbluebutton_attendee.rb +0 -21
  83. data/spec/classes/bigbluebutton_attendee_spec.rb +0 -76
  84. data/spec/controllers/bigbluebutton/recordings_controller_json_responses_spec.rb +0 -111
  85. data/spec/controllers/bigbluebutton/rooms_controller_json_responses_spec.rb +0 -203
  86. data/spec/controllers/bigbluebutton/servers_controller_json_responses_spec.rb +0 -162
@@ -14,6 +14,11 @@ class BigbluebuttonRoom < ActiveRecord::Base
14
14
  dependent: :destroy,
15
15
  inverse_of: :owner
16
16
 
17
+ has_many :meetings,
18
+ class_name: 'BigbluebuttonMeeting',
19
+ foreign_key: 'room_id',
20
+ dependent: :destroy
21
+
17
22
  has_one :room_options,
18
23
  class_name: 'BigbluebuttonRoomOptions',
19
24
  foreign_key: 'room_id',
@@ -33,7 +38,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
33
38
  validates :meetingid, :presence => true, :uniqueness => true,
34
39
  :length => { :minimum => 1, :maximum => 100 }
35
40
  validates :name, :presence => true,
36
- :length => { :minimum => 1, :maximum => 150 }
41
+ :length => { :minimum => 1, :maximum => 250 }
37
42
  validates :welcome_msg, :length => { :maximum => 250 }
38
43
  validates :private, :inclusion => { :in => [true, false] }
39
44
  validates :record_meeting, :inclusion => { :in => [true, false] }
@@ -58,8 +63,8 @@ class BigbluebuttonRoom < ActiveRecord::Base
58
63
  validates :moderator_key, :presence => true, :if => :private?
59
64
 
60
65
  # Note: these params need to be fetched from the server before being accessed
61
- attr_accessor :running, :participant_count, :moderator_count, :attendees,
62
- :has_been_forcibly_ended, :start_time, :end_time
66
+ attr_accessor :running, :participant_count, :moderator_count, :current_attendees,
67
+ :has_been_forcibly_ended, :end_time
63
68
 
64
69
  after_initialize :init
65
70
  after_create :create_room_options
@@ -74,6 +79,33 @@ class BigbluebuttonRoom < ActiveRecord::Base
74
79
  # Currently used to send the client's IP to the load balancer.
75
80
  attr_accessor :request_headers
76
81
 
82
+ scope :order_by_activity, -> (direction='ASC') {
83
+ BigbluebuttonRoom.joins(:meetings)
84
+ .group('bigbluebutton_rooms.id')
85
+ .order("MAX(bigbluebutton_meetings.create_time) #{direction}")
86
+ }
87
+
88
+ scope :search_by_terms, -> (words) {
89
+ if words.present?
90
+ words ||= []
91
+ words = [words] unless words.is_a?(Array)
92
+ query_strs = []
93
+ query_params = []
94
+ query_orders = []
95
+
96
+ words.reject(&:blank?).each do |word|
97
+ str = "name LIKE ? OR param LIKE ?"
98
+ query_strs << str
99
+ query_params += ["%#{word}%", "%#{word}%"]
100
+ query_orders += [
101
+ "CASE WHEN name LIKE '%#{word}%' THEN 1 ELSE 0 END + \
102
+ CASE WHEN param LIKE '%#{word}%' THEN 1 ELSE 0 END"
103
+ ]
104
+ end
105
+ where(query_strs.join(' OR '), *query_params.flatten).order(query_orders.join(' + ') + " DESC")
106
+ end
107
+ }
108
+
77
109
  # In case there's no room_options created yet, build one
78
110
  # (happens usually when an old database is migrated).
79
111
  def room_options_with_initialize
@@ -90,16 +122,16 @@ class BigbluebuttonRoom < ActiveRecord::Base
90
122
  # The response is parsed and stored in the model. You can access it using attributes such as:
91
123
  #
92
124
  # room.participant_count
93
- # room.attendees[0].full_name
125
+ # room.current_attendees[0].user_name
94
126
  #
95
127
  # The attributes changed are:
96
128
  # * <tt>participant_count</tt>
97
129
  # * <tt>moderator_count</tt>
98
130
  # * <tt>running</tt>
99
131
  # * <tt>has_been_forcibly_ended</tt>
100
- # * <tt>start_time</tt>
132
+ # * <tt>create_time</tt>
101
133
  # * <tt>end_time</tt>
102
- # * <tt>attendees</tt> (array of <tt>BigbluebuttonAttendee</tt>)
134
+ # * <tt>current_attendees</tt> (array of <tt>BigbluebuttonAttendee</tt>)
103
135
  #
104
136
  # Triggers API call: <tt>getMeetingInfo</tt>.
105
137
  def fetch_meeting_info
@@ -111,14 +143,13 @@ class BigbluebuttonRoom < ActiveRecord::Base
111
143
  @moderator_count = response[:moderatorCount]
112
144
  @running = response[:running]
113
145
  @has_been_forcibly_ended = response[:hasBeenForciblyEnded]
114
- @start_time = response[:startTime]
115
146
  @end_time = response[:endTime]
116
- @attendees = []
147
+ @current_attendees = []
117
148
  if response[:attendees].present?
118
149
  response[:attendees].each do |att|
119
150
  attendee = BigbluebuttonAttendee.new
120
151
  attendee.from_hash(att)
121
- @attendees << attendee
152
+ @current_attendees << attendee
122
153
  end
123
154
  end
124
155
 
@@ -156,7 +187,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
156
187
  response = server.api.end_meeting(self.meetingid, self.moderator_api_password)
157
188
 
158
189
  # enqueue an update in the meeting to end it faster
159
- Resque.enqueue(::BigbluebuttonMeetingUpdater, self.id)
190
+ Resque.enqueue(::BigbluebuttonMeetingUpdaterWorker, self.id)
160
191
 
161
192
  response
162
193
  end
@@ -172,13 +203,17 @@ class BigbluebuttonRoom < ActiveRecord::Base
172
203
  # * <tt>moderator_api_password</tt>
173
204
  #
174
205
  # Triggers API call: <tt>create</tt>.
175
- def send_create(user=nil, user_opts={})
206
+ def send_create(user=nil)
176
207
  self.meetingid = unique_meetingid() if self.meetingid.blank?
177
208
  self.moderator_api_password = internal_password() if self.moderator_api_password.blank?
178
209
  self.attendee_api_password = internal_password() if self.attendee_api_password.blank?
179
210
  self.save unless self.new_record?
180
211
 
181
- response = internal_create_meeting(user, user_opts)
212
+ # Get the user options to use when creating the meeting
213
+ user_opts = BigbluebuttonRails.configuration.get_create_options.call(self, user)
214
+ user_opts = {} if user_opts.blank?
215
+
216
+ server, response = internal_create_meeting(user, user_opts)
182
217
  unless response.nil?
183
218
  self.attendee_api_password = response[:attendeePW]
184
219
  self.moderator_api_password = response[:moderatorPW]
@@ -189,11 +224,11 @@ class BigbluebuttonRoom < ActiveRecord::Base
189
224
  self.save
190
225
 
191
226
  # creates the meeting object since the create was successful
192
- create_meeting_record(response[:metadata])
227
+ create_meeting_record(response, server, user, user_opts)
193
228
 
194
229
  # enqueue an update in the meeting with a small delay we assume to be
195
230
  # enough for the user to fully join the meeting
196
- Resque.enqueue(::BigbluebuttonMeetingUpdater, self.id, 10.seconds)
231
+ Resque.enqueue(::BigbluebuttonMeetingUpdaterWorker, self.id, 10.seconds)
197
232
  end
198
233
  end
199
234
 
@@ -229,6 +264,26 @@ class BigbluebuttonRoom < ActiveRecord::Base
229
264
  r
230
265
  end
231
266
 
267
+ def parameterized_join_url(username, role, id, options={}, user=nil)
268
+ opts = options.clone
269
+
270
+ # gets the token with the configurations for this user/room
271
+ if opts[:configToken].blank?
272
+ token = self.fetch_new_token
273
+ opts.merge!({ configToken: token }) unless token.blank?
274
+ end
275
+
276
+ # set the create time and the user id, if they exist
277
+ opts.merge!({ createTime: self.create_time }) unless self.create_time.blank? || options[:createTime].present?
278
+ opts.merge!({ userID: id }) unless id.blank? || options[:userID].present?
279
+
280
+ # Get options passed by the application, if any
281
+ user_opts = BigbluebuttonRails.configuration.get_join_options.call(self, user)
282
+ user_opts = {} if user_opts.blank?
283
+ opts.merge!(user_opts)
284
+
285
+ self.join_url(username, role, nil, opts)
286
+ end
232
287
 
233
288
  # Returns the role of the user based on the key given.
234
289
  # The return value can be <tt>:moderator</tt>, <tt>:attendee</tt>, or
@@ -236,10 +291,12 @@ class BigbluebuttonRoom < ActiveRecord::Base
236
291
  # params:: Hash with a key :key
237
292
  def user_role(params)
238
293
  role = nil
239
- if params && params.has_key?(:key)
240
- if self.moderator_key == params[:key]
294
+ key = params.is_a?(String) ? params : (params && params.has_key?(:key) ? params[:key] : nil)
295
+
296
+ unless key.blank?
297
+ if self.moderator_key == key
241
298
  role = :moderator
242
- elsif self.attendee_key == params[:key]
299
+ elsif self.attendee_key == key
243
300
  role = :attendee
244
301
  end
245
302
  end
@@ -251,8 +308,8 @@ class BigbluebuttonRoom < ActiveRecord::Base
251
308
  # if they are have all equal values.
252
309
  # From: http://alicebobandmallory.com/articles/2009/11/02/comparing-instance-variables-in-ruby
253
310
  def instance_variables_compare(o)
254
- vars = [ :@running, :@participant_count, :@moderator_count, :@attendees,
255
- :@has_been_forcibly_ended, :@start_time, :@end_time ]
311
+ vars = [ :@running, :@participant_count, :@moderator_count, :@current_attendees,
312
+ :@has_been_forcibly_ended, :@end_time ]
256
313
  Hash[*vars.map { |v|
257
314
  self.instance_variable_get(v)!=o.instance_variable_get(v) ?
258
315
  [v,o.instance_variable_get(v)] : []}.flatten]
@@ -273,7 +330,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
273
330
  # The create logic.
274
331
  # Will create the meeting in this room unless it is already running.
275
332
  # Returns true if the meeting was created.
276
- def create_meeting(user=nil, request=nil, user_opts={})
333
+ def create_meeting(user=nil, request=nil)
277
334
  fetch_is_running?
278
335
  unless is_running?
279
336
 
@@ -281,7 +338,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
281
338
  suppress(BigBlueButton::BigBlueButtonException) { send_end }
282
339
 
283
340
  add_domain_to_logout_url(request.protocol, request.host_with_port) unless request.nil?
284
- send_create(user, user_opts)
341
+ send_create(user)
285
342
  true
286
343
  else
287
344
  false
@@ -324,7 +381,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
324
381
  unless self.create_time.nil?
325
382
  attrs = {
326
383
  :running => self.running,
327
- :start_time => self.start_time.try(:utc)
384
+ :create_time => self.create_time
328
385
  }
329
386
  # note: it's important to update the 'ended' attr so the meeting is
330
387
  # reopened in case it was mistakenly considered as ended
@@ -345,7 +402,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
345
402
  end
346
403
  end
347
404
 
348
- def create_meeting_record(metadata=nil)
405
+ def create_meeting_record(response, server, user, user_opts)
349
406
  unless get_current_meeting.present?
350
407
  if self.create_time.present?
351
408
 
@@ -353,7 +410,6 @@ class BigbluebuttonRoom < ActiveRecord::Base
353
410
  # has not yet been set as ended
354
411
  self.finish_meetings
355
412
 
356
- server = BigbluebuttonRails.configuration.select_server.call(self)
357
413
  attrs = {
358
414
  room: self,
359
415
  server_url: server.url,
@@ -363,9 +419,10 @@ class BigbluebuttonRoom < ActiveRecord::Base
363
419
  recorded: self.record_meeting,
364
420
  create_time: self.create_time,
365
421
  running: self.running,
366
- ended: false,
367
- start_time: self.start_time.try(:utc)
422
+ ended: false
368
423
  }
424
+
425
+ metadata = response[:metadata]
369
426
  unless metadata.nil?
370
427
  begin
371
428
  attrs[:creator_id] = metadata[BigbluebuttonRails.configuration.metadata_user_id].to_i
@@ -375,6 +432,20 @@ class BigbluebuttonRoom < ActiveRecord::Base
375
432
  attrs[:creator_name] = nil
376
433
  end
377
434
  end
435
+
436
+ # the parameters the user might have overwritten in the create call
437
+ # need to be mapped to the name of the attrs in BigbluebuttMeeting
438
+ # note: recorded is not in the API response, so we can't just get these
439
+ # attributes from there
440
+ attrs_user = {
441
+ meetingid: user_opts[:meetingID],
442
+ name: user_opts[:name],
443
+ recorded: user_opts[:record],
444
+ creator_id: user_opts[:creator_id],
445
+ creator_name: user_opts[:creator_name]
446
+ }.delete_if { |k, v| v.nil? }
447
+ attrs.merge!(attrs_user)
448
+
378
449
  BigbluebuttonMeeting.create(attrs)
379
450
 
380
451
  Rails.logger.error "Did not create a current meeting because there was no create_time on room #{self.meetingid}"
@@ -386,15 +457,27 @@ class BigbluebuttonRoom < ActiveRecord::Base
386
457
 
387
458
  # Sets all meetings related to this room as not running
388
459
  def finish_meetings
460
+ to_be_finished = BigbluebuttonMeeting.where(ended: false, room_id: self.id).to_a
461
+ now = DateTime.now.strftime('%Q').to_i
462
+
389
463
  BigbluebuttonMeeting.where(ended: false)
390
464
  .where(room_id: self.id)
391
- .update_all(running: false, ended: true)
465
+ .update_all(running: false, ended: true, finish_time: now)
392
466
 
393
467
  # in case there are inconsistent meetings marked as running
394
468
  # but that already ended
395
469
  BigbluebuttonMeeting.where(running: true, ended: true)
396
470
  .where(room_id: self.id)
397
- .update_all(running: false, ended: true)
471
+ .update_all(running: false, ended: true, finish_time: now)
472
+
473
+ if to_be_finished.count > 0
474
+ # start trying to get the recording for this room
475
+ # since we don't have a way to know exactly when a recording is done, we
476
+ # have to keep polling the server for them
477
+ # 3 times so it tries at: 4, 9, 14 and 19
478
+ # no point trying more since there is a global synchronization process
479
+ Resque.enqueue_in(4.minutes, ::BigbluebuttonRecordingsForRoomWorker, self.id, 3)
480
+ end
398
481
  end
399
482
 
400
483
  # Gets a 'configToken' to use when joining the room.
@@ -411,15 +494,20 @@ class BigbluebuttonRoom < ActiveRecord::Base
411
494
  # Triggers API call: <tt>getDefaultConfigXML</tt>.
412
495
  # Triggers API call: <tt>setConfigXML</tt>.
413
496
  def fetch_new_token
414
- if self.room_options.is_modified?
497
+ if self.room_options.is_modified? || block_given?
415
498
  server = BigbluebuttonRails.configuration.select_server.call(self, :set_config_xml)
416
499
 
417
500
  # get the default XML we will use to create a new one
418
501
  config_xml = server.api.get_default_config_xml
419
502
 
420
- # set the options on the XML
421
- # returns true if something was changed
422
- config_xml = self.room_options.set_on_config_xml(config_xml)
503
+ if block_given?
504
+ config_xml = yield(config_xml)
505
+ else
506
+ # set the options on the XML
507
+ # returns true if something was changed
508
+ config_xml = self.room_options.set_on_config_xml(config_xml)
509
+ end
510
+
423
511
  if config_xml
424
512
  server.update_config(config_xml)
425
513
  # get the new token for the room, and return it
@@ -481,6 +569,12 @@ class BigbluebuttonRoom < ActiveRecord::Base
481
569
  server
482
570
  end
483
571
 
572
+ # Short URL for this room. Can be overwritten by applications that want to use a
573
+ # different route.
574
+ def short_path
575
+ Rails.application.routes.url_helpers.join_bigbluebutton_room_path(self)
576
+ end
577
+
484
578
  protected
485
579
 
486
580
  def create_room_options
@@ -497,25 +591,24 @@ class BigbluebuttonRoom < ActiveRecord::Base
497
591
  @moderator_count = 0
498
592
  @running = false
499
593
  @has_been_forcibly_ended = false
500
- @start_time = nil
501
594
  @end_time = nil
502
- @attendees = []
595
+ @current_attendees = []
503
596
  end
504
597
 
505
598
  def internal_create_meeting(user=nil, user_opts={})
506
599
  opts = {
507
- :record => self.record_meeting,
508
- :duration => self.duration,
509
- :moderatorPW => self.moderator_api_password,
510
- :attendeePW => self.attendee_api_password,
511
- :welcome => self.welcome_msg.blank? ? default_welcome_message : self.welcome_msg,
512
- :dialNumber => self.dial_number,
513
- :logoutURL => self.full_logout_url || self.logout_url,
514
- :maxParticipants => self.max_participants,
515
- :moderatorOnlyMessage => self.moderator_only_message,
516
- :autoStartRecording => self.auto_start_recording,
517
- :allowStartStopRecording => self.allow_start_stop_recording
518
- }.merge(user_opts)
600
+ record: record_meeting,
601
+ duration: self.duration,
602
+ moderatorPW: self.moderator_api_password,
603
+ attendeePW: self.attendee_api_password,
604
+ welcome: self.welcome_msg.blank? ? default_welcome_message : self.welcome_msg,
605
+ dialNumber: self.dial_number,
606
+ logoutURL: self.full_logout_url || self.logout_url,
607
+ maxParticipants: self.max_participants,
608
+ moderatorOnlyMessage: self.moderator_only_message,
609
+ autoStartRecording: self.auto_start_recording,
610
+ allowStartStopRecording: self.allow_start_stop_recording
611
+ }
519
612
 
520
613
  # Set the voice bridge only if the gem is configured to do so and the voice bridge
521
614
  # is not blank.
@@ -523,8 +616,6 @@ class BigbluebuttonRoom < ActiveRecord::Base
523
616
  opts.merge!({ :voiceBridge => self.voice_bridge })
524
617
  end
525
618
 
526
- opts.merge!(self.get_metadata_for_create)
527
-
528
619
  # Add information about the user that is creating the meeting (if any)
529
620
  unless user.nil?
530
621
  userid = user.send(BigbluebuttonRails.configuration.user_attr_id)
@@ -539,11 +630,18 @@ class BigbluebuttonRoom < ActiveRecord::Base
539
630
  opts.merge!({ "meta_#{BigbluebuttonRails.configuration.metadata_invitation_url}" => url })
540
631
  end
541
632
 
633
+ # Merge the metadata configured in the db
634
+ meta = get_metadata_for_create
635
+ opts.merge!(meta)
636
+
637
+ # Merge the user options, if any
638
+ opts.merge!(user_opts)
639
+
542
640
  server = BigbluebuttonRails.configuration.select_server.call(self, :create)
543
641
  server.api.request_headers = @request_headers # we need the client's IP
544
642
  response = server.api.create_meeting(self.name, self.meetingid, opts)
545
643
 
546
- response
644
+ return server, response
547
645
  end
548
646
 
549
647
  # Returns the default welcome message to be shown in a conference in case
@@ -576,18 +674,9 @@ class BigbluebuttonRoom < ActiveRecord::Base
576
674
  end
577
675
 
578
676
  def get_metadata_for_create
579
- metadata = self.metadata.inject({}) { |result, meta|
677
+ self.metadata.inject({}) { |result, meta|
580
678
  result["meta_#{meta.name}"] = meta.content; result
581
679
  }
582
-
583
- dynamic_metadata = BigbluebuttonRails.configuration.get_dynamic_metadata.call(self)
584
- unless dynamic_metadata.blank?
585
- metadata = dynamic_metadata.inject(metadata) { |result, meta|
586
- result["meta_#{meta[0]}"] = meta[1]; result
587
- }
588
- end
589
-
590
- metadata
591
680
  end
592
681
 
593
682
  private
@@ -57,7 +57,7 @@ class BigbluebuttonServer < ActiveRecord::Base
57
57
 
58
58
  # Schedules a recording update right after a recording server is added.
59
59
  after_create do
60
- Resque.enqueue(::BigbluebuttonUpdateRecordings, self.id)
60
+ Resque.enqueue(::BigbluebuttonUpdateRecordingsWorker, self.id)
61
61
  end
62
62
 
63
63
  # In case there's no config created yet, build one.
@@ -0,0 +1,10 @@
1
+ object false
2
+
3
+ node(:errors) do
4
+ @errors.map do |error|
5
+ { :status => error.code.to_s,
6
+ :title => error.title,
7
+ :detail => error.to_s
8
+ }
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ object false
2
+
3
+ node :links do
4
+ @pagination_links
5
+ end
6
+
7
+ child @rooms, :root => :data, :object_root => false, :if => lambda { |r| @rooms.size > 0 } do
8
+ node(:type) { |obj| api_type_of(obj) }
9
+ node(:id) { |obj| obj.to_param }
10
+
11
+ node :attributes do |room|
12
+ attrs = { }
13
+ [ :name, :private ].each { |attr|
14
+ attrs.merge!({ :"#{attr}" => room.send(attr) })
15
+ }
16
+ attrs
17
+ end
18
+
19
+ node :relationships, :unless => lambda { |r| r.owner.nil? } do |room|
20
+ owner = room.owner
21
+ url = polymorphic_path(owner)
22
+ { :owner =>
23
+ {
24
+ :data => {
25
+ :type => api_type_of(owner),
26
+ :id => owner.to_param,
27
+ :attributes => {
28
+ :name => owner.try(:name)
29
+ }
30
+ },
31
+ :links => {
32
+ :self => url
33
+ }
34
+ }
35
+ }
36
+ end
37
+
38
+ node :links do |room|
39
+ { self: room.short_path }
40
+ end
41
+ end
42
+
43
+ node :data, :if => lambda { |r| @rooms.size == 0 } do
44
+ []
45
+ end