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
@@ -38,7 +38,7 @@ describe BigbluebuttonRoom do
38
38
  it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
39
39
 
40
40
  it { should validate_presence_of(:name) }
41
- it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
41
+ it { should ensure_length_of(:name).is_at_least(1).is_at_most(250) }
42
42
 
43
43
  it { should validate_presence_of(:param) }
44
44
  it { should validate_uniqueness_of(:param) }
@@ -63,8 +63,8 @@ describe BigbluebuttonRoom do
63
63
  it { should accept_nested_attributes_for(:metadata).allow_destroy(true) }
64
64
 
65
65
  # attr_accessors
66
- [:running, :participant_count, :moderator_count, :attendees,
67
- :has_been_forcibly_ended, :start_time, :end_time, :external,
66
+ [:running, :participant_count, :moderator_count, :current_attendees,
67
+ :has_been_forcibly_ended, :create_time, :end_time, :external,
68
68
  :request_headers, :record_meeting, :duration].each do |attr|
69
69
  it { should respond_to(attr) }
70
70
  it { should respond_to("#{attr}=") }
@@ -80,6 +80,105 @@ describe BigbluebuttonRoom do
80
80
 
81
81
  it { should respond_to(:is_running?) }
82
82
 
83
+ describe ".order_by_activity" do
84
+ let!(:room1) { FactoryGirl.create(:bigbluebutton_room) }
85
+ let!(:room2) { FactoryGirl.create(:bigbluebutton_room) }
86
+ let!(:room3) { FactoryGirl.create(:bigbluebutton_room) }
87
+ let!(:room4) { FactoryGirl.create(:bigbluebutton_room) }
88
+ let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, create_time: Time.now - 2.hours, room: room1) }
89
+ let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, create_time: Time.now, room: room2) }
90
+ let!(:meeting3) { FactoryGirl.create(:bigbluebutton_meeting, create_time: Time.now - 1.hour, room: room3) }
91
+ let!(:meeting4) { FactoryGirl.create(:bigbluebutton_meeting, create_time: Time.now - 3.hour, room: room4) }
92
+
93
+ context "ASC" do
94
+ subject { BigbluebuttonRoom.order_by_activity }
95
+ it { subject[0].should eql(room4) }
96
+ it { subject[1].should eql(room1) }
97
+ it { subject[2].should eql(room3) }
98
+ it { subject[3].should eql(room2) }
99
+ end
100
+
101
+ context "DESC" do
102
+ subject { BigbluebuttonRoom.order_by_activity('DESC') }
103
+ it { subject[0].should eql(room2) }
104
+ it { subject[1].should eql(room3) }
105
+ it { subject[2].should eql(room1) }
106
+ it { subject[3].should eql(room4) }
107
+ end
108
+ end
109
+
110
+ describe ".search_by_terms" do
111
+ let!(:rooms) {
112
+ [
113
+ FactoryGirl.create(:bigbluebutton_room, name: "La Lo", param: "lalo-1"),
114
+ FactoryGirl.create(:bigbluebutton_room, name: "La Le", param: "lale-2"),
115
+ FactoryGirl.create(:bigbluebutton_room, name: "Li Lo", param: "lilo")
116
+ ]
117
+ }
118
+ let(:subject) { BigbluebuttonRoom.search_by_terms(terms) }
119
+
120
+ context '1 term finds something' do
121
+ let(:terms) { ['la'] }
122
+ it { subject.count.should be(2) }
123
+ it { subject.should include(rooms[0], rooms[1]) }
124
+ end
125
+
126
+ context 'composite term finds something' do
127
+ let(:terms) { ['la lo'] }
128
+ it { subject.count.should be(1) }
129
+ it { subject.should include(rooms[0]) }
130
+ end
131
+
132
+ context '2 terms find something' do
133
+ let(:terms) { ['la', 'lo'] }
134
+ it { subject.count.should be(3) }
135
+ it { subject.should include(rooms[0], rooms[1], rooms[2]) }
136
+ end
137
+
138
+ context '1 term finds nothing 1 term finds something' do
139
+ let(:terms) { ['la', 'notfound'] }
140
+ it { subject.count.should be(2) }
141
+ it { subject.should include(rooms[0], rooms[1]) }
142
+ end
143
+
144
+ context '1 term finds nothing' do
145
+ let(:terms) { ['notfound'] }
146
+ it { subject.count.should eq(0) }
147
+ end
148
+
149
+ context 'multiple terms find nothing' do
150
+ let(:terms) { ['nope', 'not', 'found'] }
151
+ it { subject.count.should eq(0) }
152
+ end
153
+
154
+ context "searches by both name and params" do
155
+ let(:terms) { ['abcdef'] }
156
+ before {
157
+ rooms[1].update_attributes(name: 'abcdef')
158
+ rooms[2].update_attributes(param: 'abcdef')
159
+ }
160
+ it { subject.count.should be(2) }
161
+ it { subject.should include(rooms[1], rooms[2]) }
162
+ end
163
+
164
+ context "returns a Relation object" do
165
+ let(:terms) { [''] }
166
+ it { subject.should be_kind_of(ActiveRecord::Relation) }
167
+ end
168
+
169
+ context "accepts a string as parameter" do
170
+ let(:terms) { 'la' }
171
+ it { subject.count.should be(2) }
172
+ it { subject.should include(rooms[0], rooms[1]) }
173
+ end
174
+
175
+ context "is chainable" do
176
+ subject { BigbluebuttonRoom.search_by_terms('l').where(id: rooms[0].id) }
177
+ it { subject.count.should be(1) }
178
+ it { subject.should include(rooms[0]) }
179
+ end
180
+ end
181
+
83
182
  describe "#user_role" do
84
183
  let(:room) { FactoryGirl.build(:bigbluebutton_room, :moderator_key => "mod", :attendee_key => "att") }
85
184
  it { should respond_to(:user_role) }
@@ -136,9 +235,9 @@ describe BigbluebuttonRoom do
136
235
  room.moderator_count.should be(0)
137
236
  room.running.should be(false)
138
237
  room.has_been_forcibly_ended.should be(false)
139
- room.start_time.should be_nil
238
+ room.create_time.should be_nil
140
239
  room.end_time.should be_nil
141
- room.attendees.should eql([])
240
+ room.current_attendees.should eql([])
142
241
  room.request_headers.should == {}
143
242
  end
144
243
 
@@ -308,10 +407,10 @@ describe BigbluebuttonRoom do
308
407
  it { room.has_been_forcibly_ended.should == false }
309
408
  it { room.participant_count.should == 0 }
310
409
  it { room.moderator_count.should == 0 }
311
- it { room.start_time.should == nil }
410
+ it { room.create_time.should == nil }
312
411
  it { room.reload.create_time.should == nil }
313
412
  it { room.end_time.should == nil }
314
- it { room.attendees.should == [] }
413
+ it { room.current_attendees.should == [] }
315
414
  end
316
415
 
317
416
  context "fetches meeting info when the meeting is running" do
@@ -325,14 +424,15 @@ describe BigbluebuttonRoom do
325
424
  it { room.has_been_forcibly_ended.should == false }
326
425
  it { room.participant_count.should == 4 }
327
426
  it { room.moderator_count.should == 2 }
328
- it { room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011") }
329
427
  it { room.reload.create_time.should == 1466876909 }
330
428
  it { room.end_time.should == nil }
331
429
  it {
332
430
  users.each do |att|
333
431
  attendee = BigbluebuttonAttendee.new
334
432
  attendee.from_hash(att)
335
- room.attendees.should include(attendee)
433
+ found = room.current_attendees.select{ |a| a.user_name == attendee.user_name }[0]
434
+ found.user_id.should eql(attendee.user_id)
435
+ found.role.should eql(attendee.role)
336
436
  end
337
437
  }
338
438
  end
@@ -432,7 +532,7 @@ describe BigbluebuttonRoom do
432
532
  it { room.send_end }
433
533
  end
434
534
 
435
- context "schedules a BigbluebuttonMeetingUpdater" do
535
+ context "schedules a BigbluebuttonMeetingUpdaterWorker" do
436
536
  before {
437
537
  room.should_receive(:select_server).and_return(mocked_server)
438
538
  mocked_api.should_receive(:end_meeting)
@@ -442,8 +542,8 @@ describe BigbluebuttonRoom do
442
542
  }
443
543
 
444
544
  subject { Resque.peek(:bigbluebutton_rails) }
445
- it("should have a job schedule") { subject.should_not be_nil }
446
- it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdater') }
545
+ it("should have a job scheduled") { subject.should_not be_nil }
546
+ it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdaterWorker') }
447
547
  it("the job should have the correct parameters") { subject['args'].should eq([room.id]) }
448
548
  end
449
549
  end
@@ -491,8 +591,9 @@ describe BigbluebuttonRoom do
491
591
 
492
592
  context "sets the room's create_time" do
493
593
  before do
594
+ # BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ expected_params })
494
595
  mocked_api.should_receive(:create_meeting)
495
- .with(room.name, room.meetingid, get_create_params(room))
596
+ .with(room.name, room.meetingid, expected_params)
496
597
  .and_return(hash_create)
497
598
  room.stub(:select_server).and_return(mocked_server)
498
599
  room.send_create
@@ -502,9 +603,9 @@ describe BigbluebuttonRoom do
502
603
  end
503
604
 
504
605
  context "sends create_meeting" do
505
-
506
606
  context "for a stored room" do
507
607
  before do
608
+ #BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ expected_params })
508
609
  mocked_api.should_receive(:create_meeting)
509
610
  .with(room.name, room.meetingid, expected_params)
510
611
  .and_return(hash_create)
@@ -520,7 +621,8 @@ describe BigbluebuttonRoom do
520
621
  context "for a new record" do
521
622
  let(:new_room) { FactoryGirl.build(:bigbluebutton_room) }
522
623
  before do
523
- params = get_create_params(new_room)
624
+ params = get_create_params(new_room)
625
+ # BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ params })
524
626
  mocked_api.should_receive(:create_meeting)
525
627
  .with(new_room.name, new_room.meetingid, params)
526
628
  .and_return(hash_create)
@@ -552,16 +654,31 @@ describe BigbluebuttonRoom do
552
654
  it { room.changed?.should be(false) }
553
655
  end
554
656
 
555
- context "passing additional options" do
657
+ context "passing metadata from the db" do
658
+ let(:user) { FactoryGirl.build(:user) }
659
+ before do
660
+ mocked_api.should_receive(:create_meeting)
661
+ .with(room.name, room.meetingid, get_create_params(room, user))
662
+ .and_return(hash_create)
663
+ room.stub(:select_server).and_return(mocked_server)
664
+ room.send_create(user)
665
+ end
666
+ it { room.attendee_api_password.should be(new_attendee_api_password) }
667
+ it { room.moderator_api_password.should be(new_moderator_api_password) }
668
+ it { room.changed?.should be(false) }
669
+ end
670
+
671
+ context "passing additional user options" do
556
672
  let(:user) { FactoryGirl.build(:user) }
557
673
  let(:user_opts) { { :record_meeting => false, :other => true } }
558
674
  before do
559
675
  params = get_create_params(room, user).merge(user_opts)
676
+ BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ user_opts })
560
677
  mocked_api.should_receive(:create_meeting)
561
678
  .with(room.name, room.meetingid, params)
562
679
  .and_return(hash_create)
563
680
  room.stub(:select_server).and_return(mocked_server)
564
- room.send_create(user, user_opts)
681
+ room.send_create(user)
565
682
  end
566
683
  it { room.attendee_api_password.should be(new_attendee_api_password) }
567
684
  it { room.moderator_api_password.should be(new_moderator_api_password) }
@@ -572,9 +689,8 @@ describe BigbluebuttonRoom do
572
689
  before do
573
690
  room.update_attributes(:voice_bridge => nil)
574
691
  hash_create.delete(:voiceBridge)
575
-
576
692
  mocked_api.should_receive(:create_meeting)
577
- .with(room.name, room.meetingid, get_create_params(room))
693
+ .with(room.name, room.meetingid, expected_params)
578
694
  .and_return(hash_create)
579
695
  room.stub(:select_server).and_return(mocked_server)
580
696
  room.send_create
@@ -598,7 +714,6 @@ describe BigbluebuttonRoom do
598
714
  room.update_attributes(:voice_bridge => voice_bridge)
599
715
  create_params = get_create_params(room)
600
716
  create_params.merge!({ :voiceBridge => voice_bridge })
601
-
602
717
  mocked_api.should_receive(:create_meeting)
603
718
  .with(room.name, room.meetingid, create_params)
604
719
  .and_return(hash_create)
@@ -612,9 +727,8 @@ describe BigbluebuttonRoom do
612
727
  let(:voice_bridge) { SecureRandom.random_number(99999) }
613
728
  before do
614
729
  room.update_attributes(:voice_bridge => "")
615
-
616
730
  mocked_api.should_receive(:create_meeting)
617
- .with(room.name, room.meetingid, get_create_params(room))
731
+ .with(room.name, room.meetingid, expected_params)
618
732
  .and_return(hash_create)
619
733
  room.stub(:select_server).and_return(mocked_server)
620
734
  room.send_create
@@ -624,30 +738,43 @@ describe BigbluebuttonRoom do
624
738
  end
625
739
 
626
740
  context "creates a meeting record" do
627
- before do
628
- mocked_api.should_receive(:create_meeting)
629
- .with(room.name, room.meetingid, expected_params)
630
- .and_return(hash_create)
631
- room.stub(:select_server).and_return(mocked_server)
741
+ context "set the correct attributes in the record" do
742
+ before do
743
+ mocked_api.should_receive(:create_meeting)
744
+ .with(room.name, room.meetingid, expected_params)
745
+ .and_return(hash_create)
746
+ room.stub(:select_server).and_return(mocked_server)
632
747
 
633
- expect {
634
- room.send_create
635
- }.to change{ BigbluebuttonMeeting.count }.by(1)
748
+ expect {
749
+ room.send_create
750
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
751
+ end
752
+ subject { BigbluebuttonMeeting.last }
753
+ it { subject.room.should eql(room) }
754
+ it { subject.server_url.should eql(mocked_server.url) }
755
+ it { subject.server_secret.should eql(mocked_server.secret) }
756
+ it { subject.meetingid.should eql(room.meetingid) }
757
+ it { subject.name.should eql(room.name) }
758
+ it { subject.recorded.should eql(room.record_meeting) }
759
+ it { subject.create_time.should eql(room.create_time) }
760
+ it { subject.ended.should eql(false) }
761
+ end
762
+
763
+ context "calls create_meeting_record with the correct arguments" do
764
+ let(:user_opts) { { opt1: 1, opt2: 'two' } }
765
+ let(:response) { { response: 1 } }
766
+ before do
767
+ BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ user_opts })
768
+ room.should_receive(:internal_create_meeting) do
769
+ ['my-server', response]
770
+ end
771
+ room.should_receive(:create_meeting_record).with(response, 'my-server', 'my-user', user_opts)
772
+ end
773
+ it { room.send_create('my-user') }
636
774
  end
637
- subject { BigbluebuttonMeeting.last }
638
- it { subject.room.should eql(room) }
639
- it { subject.server_url.should eql(mocked_server.url) }
640
- it { subject.server_secret.should eql(mocked_server.secret) }
641
- it { subject.meetingid.should eql(room.meetingid) }
642
- it { subject.name.should eql(room.name) }
643
- it { subject.recorded.should eql(room.record_meeting) }
644
- it { subject.create_time.should eql(room.create_time) }
645
- it { subject.create_time.should eql(room.create_time) }
646
- it { subject.start_time.should eql(room.start_time) }
647
- it { subject.ended.should eql(false) }
648
775
  end
649
776
 
650
- context "enqueues a BigbluebuttonMeetingUpdater" do
777
+ context "enqueues a BigbluebuttonMeetingUpdaterWorker" do
651
778
  before do
652
779
  mocked_api.should_receive(:create_meeting)
653
780
  .with(room.name, room.meetingid, expected_params)
@@ -660,7 +787,7 @@ describe BigbluebuttonRoom do
660
787
  end
661
788
  subject { Resque.peek(:bigbluebutton_rails) }
662
789
  it("should have a job schedule") { subject.should_not be_nil }
663
- it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdater') }
790
+ it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdaterWorker') }
664
791
  it("the job should have the correct parameters") { subject['args'].should eq([room.id, 10]) }
665
792
  end
666
793
  end
@@ -744,6 +871,7 @@ describe BigbluebuttonRoom do
744
871
  before do
745
872
  room.full_logout_url = "full-version-of-logout-url"
746
873
  hash = get_create_params(room).merge({ :logoutURL => "full-version-of-logout-url" })
874
+ # BigbluebuttonRails.configuration.should_receive(:get_create_options).and_return(Proc.new{ hash })
747
875
  mocked_api.should_receive(:create_meeting).
748
876
  with(room.name, room.meetingid, hash).and_return(hash_create)
749
877
  room.stub(:select_server).and_return(mocked_server)
@@ -890,6 +1018,164 @@ describe BigbluebuttonRoom do
890
1018
  end
891
1019
  end
892
1020
 
1021
+ describe "#parameterized_join_url" do
1022
+ let(:username) { Forgery(:name).full_name }
1023
+ let(:role) { :attendee }
1024
+ let(:id) { 'fake-user-id' }
1025
+
1026
+ context "sets a config token" do
1027
+ context "when it exists" do
1028
+ before {
1029
+ room.create_time = nil
1030
+ room.should_receive(:fetch_new_token).and_return('fake-token')
1031
+ room.should_receive(:join_url).with(username, role, nil, { configToken: 'fake-token' })
1032
+ }
1033
+ it { room.parameterized_join_url(username, role, nil) }
1034
+ end
1035
+
1036
+ context "not when it doesn't exist" do
1037
+ before {
1038
+ room.create_time = nil
1039
+ room.should_receive(:fetch_new_token).and_return(nil)
1040
+ room.should_receive(:join_url).with(username, role, nil, { })
1041
+ }
1042
+ it { room.parameterized_join_url(username, role, nil) }
1043
+ end
1044
+
1045
+ context "not when a token is passed in the options" do
1046
+ before {
1047
+ room.create_time = nil
1048
+ room.should_not_receive(:fetch_new_token)
1049
+ room.should_receive(:join_url).with(username, role, nil, { configToken: "any" })
1050
+ }
1051
+ it { room.parameterized_join_url(username, role, nil, { configToken: "any" }) }
1052
+ end
1053
+ end
1054
+
1055
+ context "sets a create time" do
1056
+ context "when it exists" do
1057
+ before {
1058
+ room.stub(:fetch_new_token).and_return(nil)
1059
+ room.should_receive(:join_url).with(username, role, nil, { createTime: room.create_time })
1060
+ }
1061
+ it { room.parameterized_join_url(username, role, nil) }
1062
+ end
1063
+
1064
+ context "when it doesn't exist" do
1065
+ before {
1066
+ room.create_time = nil
1067
+ room.stub(:fetch_new_token).and_return(nil)
1068
+ room.should_receive(:join_url).with(username, role, nil, { })
1069
+ }
1070
+ it { room.parameterized_join_url(username, role, nil) }
1071
+ end
1072
+ end
1073
+
1074
+ context "sets a user id" do
1075
+ context "when it exists" do
1076
+ before {
1077
+ room.create_time = nil
1078
+ room.stub(:fetch_new_token).and_return(nil)
1079
+ room.should_receive(:join_url).with(username, role, nil, { userID: 'fake-user-id' })
1080
+ }
1081
+ it { room.parameterized_join_url(username, role, 'fake-user-id') }
1082
+ end
1083
+
1084
+ context "when it doesn't exist" do
1085
+ before {
1086
+ room.create_time = nil
1087
+ room.stub(:fetch_new_token).and_return(nil)
1088
+ room.should_receive(:join_url).with(username, role, nil, { })
1089
+ }
1090
+ it { room.parameterized_join_url(username, role, nil) }
1091
+ end
1092
+ end
1093
+
1094
+ context "uses the options in the parameters" do
1095
+ context "when the are set" do
1096
+ let(:options) { { option1: 'value1' } }
1097
+ before {
1098
+ room.create_time = nil
1099
+ room.stub(:fetch_new_token).and_return(nil)
1100
+ room.should_receive(:join_url).with(username, role, nil, options)
1101
+ }
1102
+ it { room.parameterized_join_url(username, role, nil, options) }
1103
+ end
1104
+
1105
+ context "overrides the options set internally by the method" do
1106
+ let(:options) { { option1: 'value1', configToken: 'opts-token', createTime: 123, userID: 'opts-userid' } }
1107
+ before {
1108
+ room.stub(:fetch_new_token).and_return('valid')
1109
+ room.should_receive(:join_url).with(username, role, nil, options)
1110
+ }
1111
+ it { room.parameterized_join_url(username, role, 'opts-userid', options) }
1112
+ end
1113
+ end
1114
+
1115
+ context "uses the options passed by the application" do
1116
+ context "when the are set" do
1117
+ let(:options) { { option1: 'value1' } }
1118
+ before {
1119
+ BigbluebuttonRails.configuration.stub(:get_join_options).and_return(Proc.new{ options })
1120
+ room.create_time = nil
1121
+ room.stub(:fetch_new_token).and_return(nil)
1122
+ room.should_receive(:join_url).with(username, role, nil, options)
1123
+ }
1124
+ it { room.parameterized_join_url(username, role, nil, {}) }
1125
+ end
1126
+
1127
+ context "overrides the options set internally by the method" do
1128
+ let(:options) { { option1: 'value1', configToken: 'valid', createTime: 'valid', userID: 'valid' } }
1129
+ let(:expected_options) { { option1: 'value1', configToken: 'valid', createTime: 'valid', userID: 'valid' } }
1130
+ before {
1131
+ BigbluebuttonRails.configuration.stub(:get_join_options).and_return(Proc.new{ options })
1132
+ room.stub(:fetch_new_token).and_return('invalid')
1133
+ room.should_receive(:join_url).with(username, role, nil, expected_options)
1134
+ }
1135
+ it { room.parameterized_join_url(username, role, 'invalid', {}) }
1136
+ end
1137
+
1138
+ context "calls get_join_options with the correct parameters" do
1139
+ context "if the user is passed in the arguments" do
1140
+ let(:user) { 'any user' }
1141
+ before {
1142
+ proc = double(Proc)
1143
+ proc.should_receive(:call).with(room, user)
1144
+ BigbluebuttonRails.configuration.should_receive(:get_join_options).and_return(proc)
1145
+ room.stub(:fetch_new_token).and_return(nil)
1146
+ room.stub(:join_url)
1147
+ }
1148
+ it { room.parameterized_join_url(username, role, nil, {}, user) }
1149
+ end
1150
+
1151
+ context "if the user is not passed in the arguments" do
1152
+ before {
1153
+ proc = double(Proc)
1154
+ proc.should_receive(:call).with(room, nil)
1155
+ BigbluebuttonRails.configuration.should_receive(:get_join_options).and_return(proc)
1156
+ room.stub(:fetch_new_token).and_return(nil)
1157
+ room.stub(:join_url)
1158
+ }
1159
+ it { room.parameterized_join_url(username, role, nil, {}, nil) }
1160
+ end
1161
+ end
1162
+ end
1163
+
1164
+ context "returns #join_url" do
1165
+ let(:expected_url) { 'https://fake-return-url.no/join?here=1' }
1166
+ before {
1167
+ room.stub(:fetch_new_token).and_return('fake-token')
1168
+ room.should_receive(:join_url)
1169
+ .with(username, role, nil, {
1170
+ userID: 'fake-user-id', configToken: 'fake-token', createTime: room.create_time
1171
+ }).and_return(expected_url)
1172
+ }
1173
+ it {
1174
+ room.parameterized_join_url(username, role, 'fake-user-id').should eql(expected_url)
1175
+ }
1176
+ end
1177
+ end
1178
+
893
1179
  describe "#fetch_new_token" do
894
1180
  let(:config_xml) {
895
1181
  '<config>
@@ -942,8 +1228,25 @@ describe BigbluebuttonRoom do
942
1228
  }
943
1229
  it("returns nil") { room.fetch_new_token.should be_nil }
944
1230
  end
945
- end
946
1231
 
1232
+ context "when used with a block" do
1233
+ before {
1234
+ room.room_options.should_receive(:is_modified?)
1235
+ .and_return(true)
1236
+ mocked_api.should_receive(:get_default_config_xml).and_return(config_xml)
1237
+ room.room_options.should_not_receive(:set_on_config_xml)
1238
+ mocked_server.should_receive(:update_config).with('fake-xml-from-block')
1239
+ mocked_api.should_receive(:set_config_xml)
1240
+ .with(room.meetingid, 'fake-xml-from-block')
1241
+ }
1242
+ it("uses the xml returned by the block") {
1243
+ room.fetch_new_token do |xml|
1244
+ xml.should eql(config_xml)
1245
+ 'fake-xml-from-block'
1246
+ end
1247
+ }
1248
+ end
1249
+ end
947
1250
  end
948
1251
 
949
1252
  context "#available_layouts" do
@@ -1129,7 +1432,7 @@ describe BigbluebuttonRoom do
1129
1432
  context "when the conference is not running" do
1130
1433
  before {
1131
1434
  room.should_receive(:is_running?).and_return(false)
1132
- room.should_receive(:send_create).with(user, {})
1435
+ room.should_receive(:send_create).with(user)
1133
1436
  room.should_receive(:send_end)
1134
1437
  }
1135
1438
  subject { room.create_meeting(user) }
@@ -1153,7 +1456,7 @@ describe BigbluebuttonRoom do
1153
1456
  context "ignores exceptions raised by send_end (for when there's no meeting created)" do
1154
1457
  before {
1155
1458
  room.should_receive(:is_running?).and_return(false)
1156
- room.should_receive(:send_create).with(user, {})
1459
+ room.should_receive(:send_create).with(user)
1157
1460
  room.should_receive(:send_end) { raise BigBlueButton::BigBlueButtonException.new('test') }
1158
1461
  }
1159
1462
  it {
@@ -1170,9 +1473,14 @@ describe BigbluebuttonRoom do
1170
1473
  it { should respond_to(:"full_logout_url=") }
1171
1474
  end
1172
1475
 
1476
+ describe "#short_path" do
1477
+ subject { FactoryGirl.create(:bigbluebutton_room) }
1478
+ it { subject.short_path.should eql("/bigbluebutton/rooms/#{subject.to_param}/join") }
1479
+ end
1480
+
1173
1481
  describe "#select_server" do
1174
- let(:server) { FactoryGirl.create(:bigbluebutton_server) }
1175
- let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1482
+ let!(:server) { FactoryGirl.create(:bigbluebutton_server) }
1483
+ let!(:room) { FactoryGirl.create(:bigbluebutton_room) }
1176
1484
 
1177
1485
  it { room.respond_to?(:select_server, true).should be(true) }
1178
1486
 
@@ -1205,46 +1513,13 @@ describe BigbluebuttonRoom do
1205
1513
  room.send(:get_metadata_for_create).should == result
1206
1514
  }
1207
1515
  end
1208
-
1209
- context "returns the dynamic metadata, if any" do
1210
- before {
1211
- BigbluebuttonRails.configure do |config|
1212
- config.get_dynamic_metadata = Proc.new do |room|
1213
- { "test1" => "value1", "test2" => "value2" }
1214
- end
1215
- end
1216
- }
1217
-
1218
- it {
1219
- result = { "meta_test1" => "value1", "meta_test2" => "value2" }
1220
- room.send(:get_metadata_for_create).should eql(result)
1221
- }
1222
- end
1223
-
1224
- context "gives priority to the dynamic metadata" do
1225
- before {
1226
- BigbluebuttonRails.configure do |config|
1227
- config.get_dynamic_metadata = Proc.new do |room|
1228
- { "test1" => "value1", "test2" => "value2" }
1229
- end
1230
- end
1231
-
1232
- @m1 = FactoryGirl.create(:bigbluebutton_room_metadata, owner: room, name: "test1", content: "content overwritten")
1233
- @m2 = FactoryGirl.create(:bigbluebutton_room_metadata, owner: room, name: "other", content: "other content")
1234
- }
1235
-
1236
- it {
1237
- result = { "meta_test1" => "value1", "meta_test2" => "value2", "meta_other" => "other content" }
1238
- room.send(:get_metadata_for_create).should eql(result)
1239
- }
1240
- end
1241
1516
  end
1242
1517
 
1243
1518
  describe "#get_current_meeting" do
1244
1519
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1245
1520
 
1246
- context "if there's no start_time set in the room" do
1247
- before { room.start_time = nil }
1521
+ context "if there's no create_time set in the room" do
1522
+ before { room.create_time = nil }
1248
1523
  it { room.get_current_meeting.should be_nil }
1249
1524
  end
1250
1525
 
@@ -1280,7 +1555,7 @@ describe BigbluebuttonRoom do
1280
1555
  before {
1281
1556
  room.create_time = Time.now.utc
1282
1557
  room.running = !room.running # to change its default value
1283
- room.start_time = Time.at(Time.now.to_i - 123) # to change its default value
1558
+ room.create_time = Time.at(Time.now.to_i - 123) # to change its default value
1284
1559
  }
1285
1560
 
1286
1561
  context "and no metadata was passed" do
@@ -1294,7 +1569,7 @@ describe BigbluebuttonRoom do
1294
1569
  }
1295
1570
  subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1296
1571
  it("sets running") { subject.running.should eq(room.running) }
1297
- it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1572
+ it("sets create_time") { subject.create_time.should eq(room.create_time.to_i) }
1298
1573
  it("doesn't set creator_id") { subject.creator_id.should be_nil }
1299
1574
  it("doesn't set creator_name") { subject.creator_name.should be_nil }
1300
1575
  end
@@ -1310,7 +1585,7 @@ describe BigbluebuttonRoom do
1310
1585
  }
1311
1586
  subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1312
1587
  it("sets running") { subject.running.should eq(room.running) }
1313
- it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1588
+ it("sets create_time") { subject.create_time.should eq(room.create_time.to_i) }
1314
1589
  it("sets creator_id") { subject.creator_id.should eq(user.id) }
1315
1590
  it("sets creator_name") { subject.creator_name.should eq(user.name) }
1316
1591
  end
@@ -1326,7 +1601,7 @@ describe BigbluebuttonRoom do
1326
1601
  }
1327
1602
  subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1328
1603
  it("sets running") { subject.running.should eq(room.running) }
1329
- it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1604
+ it("sets create_time") { subject.create_time.should eq(room.create_time.to_i) }
1330
1605
  it("sets ended") { subject.ended.should be(false) }
1331
1606
  end
1332
1607
  end
@@ -1340,7 +1615,7 @@ describe BigbluebuttonRoom do
1340
1615
  let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true, create_time: room.create_time) }
1341
1616
  subject {
1342
1617
  expect {
1343
- room.create_meeting_record
1618
+ room.create_meeting_record({}, server, nil, {})
1344
1619
  }.not_to change{ BigbluebuttonMeeting.count }
1345
1620
  }
1346
1621
  it { BigbluebuttonMeeting.where(room: room).count.should be(1) }
@@ -1368,15 +1643,14 @@ describe BigbluebuttonRoom do
1368
1643
  room.create_time = Time.now.utc
1369
1644
  room.running = !room.running # to change its default value
1370
1645
  room.record_meeting = !room.record_meeting # to change its default value
1371
- room.start_time = Time.at(Time.now.to_i - 123) # to change its default value
1646
+ room.create_time = Time.at(Time.now.to_i - 123) # to change its default value
1372
1647
  }
1373
1648
 
1374
1649
  context "if there's no meeting associated yet creates one" do
1375
- context "and no metadata was passed" do
1650
+ context "and there's no metadata in the response" do
1376
1651
  before(:each) {
1377
1652
  expect {
1378
- room.should_receive(:select_server).and_return(server)
1379
- room.create_meeting_record
1653
+ room.create_meeting_record({}, server, nil, {})
1380
1654
  }.to change{ BigbluebuttonMeeting.count }.by(1)
1381
1655
  }
1382
1656
  subject { BigbluebuttonMeeting.last }
@@ -1387,21 +1661,45 @@ describe BigbluebuttonRoom do
1387
1661
  it("sets name") { subject.name.should eq(room.name) }
1388
1662
  it("sets recorded") { subject.recorded.should eq(room.record_meeting) }
1389
1663
  it("sets running") { subject.running.should eq(room.running) }
1390
- it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1664
+ it("sets create_time") { subject.create_time.should eq(room.create_time.to_i) }
1391
1665
  it("doesn't set creator_id") { subject.creator_id.should be_nil }
1392
1666
  it("doesn't set creator_name") { subject.creator_name.should be_nil }
1393
1667
  end
1394
1668
 
1395
- context "and metadata was passed" do
1669
+ context "and there's metadata in the response" do
1396
1670
  before(:each) {
1397
1671
  expect {
1398
- room.create_meeting_record(metadata)
1672
+ room.create_meeting_record({ metadata: metadata }, server, nil, {})
1399
1673
  }.to change{ BigbluebuttonMeeting.count }.by(1)
1400
1674
  }
1401
1675
  subject { BigbluebuttonMeeting.last }
1402
1676
  it("sets creator_id") { subject.creator_id.should eq(user.id) }
1403
1677
  it("sets creator_name") { subject.creator_name.should eq(user.name) }
1404
1678
  end
1679
+
1680
+ context "and there are user attributes" do
1681
+ let(:user_attrs) {
1682
+ {
1683
+ meetingID: room.meetingid + "-2",
1684
+ name: room.name + "-2",
1685
+ record: false, # important to be false here
1686
+ creator_name: "can override the creator name",
1687
+ creator_id: -10
1688
+ }
1689
+ }
1690
+ before {
1691
+ room.record_meeting = true
1692
+ expect {
1693
+ room.create_meeting_record({}, server, nil, user_attrs)
1694
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
1695
+ }
1696
+ subject { BigbluebuttonMeeting.last }
1697
+ it("sets meetingid") { subject.meetingid.should eql(room.meetingid + '-2') }
1698
+ it("sets name") { subject.name.should eql(room.name + '-2') }
1699
+ it("sets recorded") { subject.recorded.should be(false) }
1700
+ it("sets creator name") { subject.creator_name.should eql("can override the creator name") }
1701
+ it("sets creator id") { subject.creator_id.should eql(-10) }
1702
+ end
1405
1703
  end
1406
1704
 
1407
1705
  context "if there were already old meetings associated with the room, finishes them" do
@@ -1411,7 +1709,7 @@ describe BigbluebuttonRoom do
1411
1709
  before(:each) {
1412
1710
  BigbluebuttonMeeting.where(room: room, ended: false).count.should be(2)
1413
1711
  expect {
1414
- room.create_meeting_record(metadata)
1712
+ room.create_meeting_record({ metadata: metadata }, server, nil, {})
1415
1713
  }.to change{ BigbluebuttonMeeting.count }.by(1)
1416
1714
  }
1417
1715
  it { BigbluebuttonMeeting.where(room: room).count.should be(3) }
@@ -1444,16 +1742,45 @@ describe BigbluebuttonRoom do
1444
1742
 
1445
1743
  context "if there's a current meeting not running, ends it" do
1446
1744
  let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: false, create_time: room.create_time) }
1447
- before(:each) { room.finish_meetings }
1745
+ let!(:now) { DateTime.now }
1746
+ before(:each) {
1747
+ DateTime.stub(:now).and_return(now)
1748
+ room.finish_meetings
1749
+ }
1448
1750
  it { meeting.reload.running.should be(false) }
1449
1751
  it { meeting.reload.ended.should be(true) }
1752
+ it { meeting.reload.finish_time.should be(now.strftime("%Q").to_i) }
1450
1753
  end
1451
1754
 
1452
1755
  context "ends meetings are already ended but still set as running" do
1453
1756
  let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: true, running: true) }
1454
- before(:each) { room.finish_meetings }
1757
+ let!(:now) { DateTime.now }
1758
+ before(:each) {
1759
+ DateTime.stub(:now).and_return(now)
1760
+ room.finish_meetings
1761
+ }
1455
1762
  it { meeting.reload.running.should be(false) }
1456
1763
  it { meeting.reload.ended.should be(true) }
1764
+ it { meeting.reload.finish_time.should be(now.strftime("%Q").to_i) }
1765
+ end
1766
+
1767
+ context "enqueues workers to fetch recordings" do
1768
+ context "if at least one meeting was ended" do
1769
+ let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true) }
1770
+ let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true) }
1771
+ before {
1772
+ expect(Resque).to receive(:enqueue_in).with(4.minutes, ::BigbluebuttonRecordingsForRoomWorker, room.id, 3)
1773
+ }
1774
+ it { room.finish_meetings }
1775
+ end
1776
+
1777
+ context "not if no meeting was ended" do
1778
+ let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: true, running: true) }
1779
+ before {
1780
+ expect(Resque).not_to receive(:enqueue_in)
1781
+ }
1782
+ it { room.finish_meetings }
1783
+ end
1457
1784
  end
1458
1785
  end
1459
1786
 
@@ -1464,6 +1791,7 @@ describe BigbluebuttonRoom do
1464
1791
  it "sets the request headers"
1465
1792
  it "calls api.create_meeting"
1466
1793
  it "accepts additional user options to override the options in the database"
1794
+ it "returns the server selected and the response"
1467
1795
 
1468
1796
  context "adds the invitation URL, if any" do
1469
1797
  before { mock_server_and_api }
@@ -1520,62 +1848,21 @@ describe BigbluebuttonRoom do
1520
1848
  end
1521
1849
  end
1522
1850
 
1523
- context "adds the dynamic metadata, if any" do
1851
+ context "adds the options from user_opts" do
1524
1852
  before { mock_server_and_api }
1525
1853
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1526
-
1854
+ let(:user_opts) { { "meta_test1" => "value1", "meta_test2" => "value2" } }
1527
1855
  before {
1528
1856
  room.stub(:select_server).and_return(mocked_server)
1529
1857
  mocked_api.stub(:"request_headers=")
1530
- }
1531
-
1532
- it { room.should_not respond_to(:dynamic_metadata) }
1533
-
1534
- context "doesn't havedefault dynamic metadata" do
1535
- before {
1536
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1537
- opts.each do |key, value|
1538
- key.should_not match(/meta_/)
1539
- end
1540
- end
1541
- }
1542
- it { room.send(:internal_create_meeting) }
1543
- end
1544
-
1545
- context "doesn't add the dynamic metadata if it returns nil" do
1546
- before {
1547
- BigbluebuttonRails.configure do |config|
1548
- config.get_dynamic_metadata = Proc.new do |room|
1549
- nil
1550
- end
1551
- end
1552
-
1553
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1554
- opts.each do |key, value|
1555
- key.should_not match(/meta_/)
1556
- end
1557
- end
1558
- }
1559
-
1560
- it { room.send(:internal_create_meeting) }
1561
- end
1562
-
1563
- context "adds the value returned by BigbluebuttonRoom#invitation_url" do
1564
- before {
1565
- BigbluebuttonRails.configure do |config|
1566
- config.get_dynamic_metadata = Proc.new do |room|
1567
- { "test1" => "value1", "test2" => "value2" }
1568
- end
1569
- end
1570
1858
 
1571
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1572
- opts.should include('meta_test1' => 'value1')
1573
- opts.should include('meta_test2' => 'value2')
1574
- end
1575
- }
1859
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1860
+ opts.should include('meta_test1' => 'value1')
1861
+ opts.should include('meta_test2' => 'value2')
1862
+ end
1863
+ }
1576
1864
 
1577
- it { room.send(:internal_create_meeting) }
1578
- end
1865
+ it { room.send(:internal_create_meeting, nil, user_opts) }
1579
1866
  end
1580
1867
  end
1581
1868
  end
@@ -1594,12 +1881,12 @@ def get_create_params(room, user=nil)
1594
1881
  :autoStartRecording => room.auto_start_recording,
1595
1882
  :allowStartStopRecording => room.allow_start_stop_recording
1596
1883
  }
1597
- room.metadata.each { |meta| params["meta_#{meta.name}"] = meta.content }
1598
1884
  unless user.nil?
1599
1885
  userid = user.send(:id)
1600
1886
  username = user.send(:name)
1601
1887
  params.merge!({ "meta_bbbrails-user-id" => userid })
1602
1888
  params.merge!({ "meta_bbbrails-user-name" => username })
1603
1889
  end
1890
+ room.metadata.each { |meta| params["meta_#{meta.name}"] = meta.content }
1604
1891
  params
1605
1892
  end