bigbluebutton_rails 0.0.2 → 0.0.3

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 (43) hide show
  1. data/CHANGELOG.rdoc +9 -1
  2. data/Gemfile.lock +3 -3
  3. data/README.rdoc +56 -21
  4. data/Rakefile +1 -0
  5. data/app/controllers/bigbluebutton/rooms_controller.rb +92 -35
  6. data/app/models/bigbluebutton_room.rb +136 -27
  7. data/app/models/bigbluebutton_server.rb +22 -6
  8. data/app/views/bigbluebutton/rooms/_form.html.erb +31 -6
  9. data/app/views/bigbluebutton/rooms/edit.html.erb +1 -1
  10. data/app/views/bigbluebutton/rooms/index.html.erb +20 -8
  11. data/app/views/bigbluebutton/rooms/invite.html.erb +56 -0
  12. data/app/views/bigbluebutton/rooms/{join_wait.html.erb → join.html.erb} +16 -12
  13. data/app/views/bigbluebutton/rooms/new.html.erb +1 -1
  14. data/app/views/bigbluebutton/rooms/show.html.erb +33 -9
  15. data/app/views/bigbluebutton/servers/edit.html.erb +1 -1
  16. data/app/views/bigbluebutton/servers/index.html.erb +6 -4
  17. data/app/views/bigbluebutton/servers/new.html.erb +1 -1
  18. data/app/views/bigbluebutton/servers/show.html.erb +5 -5
  19. data/bigbluebutton_rails.gemspec +1 -1
  20. data/config/locales/en.yml +31 -0
  21. data/lib/bigbluebutton_rails/controller_methods.rb +7 -1
  22. data/lib/bigbluebutton_rails/rails/routes.rb +10 -1
  23. data/lib/bigbluebutton_rails/version.rb +1 -1
  24. data/lib/bigbluebutton_rails.rb +0 -1
  25. data/lib/classes/bigbluebutton_attendee.rb +2 -0
  26. data/lib/generators/bigbluebutton_rails/install_generator.rb +2 -1
  27. data/lib/generators/bigbluebutton_rails/public_generator.rb +0 -1
  28. data/lib/generators/bigbluebutton_rails/templates/migration.rb +8 -2
  29. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +339 -88
  30. data/spec/factories/bigbluebutton_room.rb +5 -3
  31. data/spec/factories/user.rb +3 -0
  32. data/spec/generators/public_generator_spec.rb +0 -1
  33. data/spec/generators/views_generator_spec.rb +1 -1
  34. data/spec/models/bigbluebutton_room_spec.rb +276 -177
  35. data/spec/models/bigbluebutton_server_spec.rb +117 -96
  36. data/spec/routing/bigbluebutton/rooms_routing_spec.rb +24 -0
  37. data/spec/support/matchers/shoulda/be_boolean.rb +38 -0
  38. data/spec/support/mocked_server.rb +14 -0
  39. metadata +26 -26
  40. data/config/routes.rb +0 -2
  41. data/lib/classes/bigbluebutton_meeting.rb +0 -18
  42. data/lib/generators/bigbluebutton_rails/templates/public/javascripts/heartbeat.js +0 -54
  43. data/spec/classes/bigbluebutton_meeting_spec.rb +0 -62
data/CHANGELOG.rdoc CHANGED
@@ -1,6 +1,14 @@
1
+ == 0.0.3
2
+
3
+ * Rooms can be public or private
4
+ * New route RoomsController#invite used to request a password to join a room or to allow anonymous users to join.
5
+ * Room's "meeting_id" attribute renamed to "meetingid".
6
+ * A room can have it's meetingid randomly generated for each "send_create" call if randomize_meetingid is set.
7
+ * New attributes for rooms: logout_url, dial_number, voice_bridge and max_participant.
8
+
1
9
  == 0.0.2
2
10
 
3
- * New "fetch" methods in BigbluebuttonRooms to fetch info about meetings from BBB and store in the model.
11
+ * New "fetch" and "send" methods in BigbluebuttonRooms to fetch info about meetings from BBB and store in the model.
4
12
  * New class BigbluebuttonAttendee to store attendee information returned by BBB in get_meeting_info.
5
13
  * New class BigbluebuttonMeeting to store meeting information returned by BBB in get_meetings.
6
14
 
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bigbluebutton_rails (0.0.2)
5
- bigbluebutton-api-ruby (~> 0.0.9)
4
+ bigbluebutton_rails (0.0.3)
5
+ bigbluebutton-api-ruby (~> 0.0.10)
6
6
  rails (~> 3.0.3)
7
7
 
8
8
  GEM
@@ -36,7 +36,7 @@ GEM
36
36
  activesupport (= 3.0.6)
37
37
  activesupport (3.0.6)
38
38
  arel (2.0.9)
39
- bigbluebutton-api-ruby (0.0.9)
39
+ bigbluebutton-api-ruby (0.0.10)
40
40
  nokogiri (~> 1.4.0)
41
41
  builder (2.1.2)
42
42
  diff-lcs (1.1.2)
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = BigBlueButton on Rails
2
2
 
3
- BigBlueButton (http://bigbluebutton.org) integration for Ruby on Rails 3.
3
+ {BigBlueButton}[http://bigbluebutton.org] integration for Ruby on Rails 3.
4
4
 
5
5
  Features:
6
6
  * Allows multiple servers and multiple conference rooms
@@ -9,11 +9,12 @@ Features:
9
9
  * Easy integration with authentication and authorization mechanisms, such as Devise and CanCan
10
10
 
11
11
  Future:
12
+ * Private room and invitations to allow visitants to join conferences (using a password or not).
12
13
  * Friendly URLs (e.g. http://somewhere.com/my-server/my-room)
13
14
  * Random meeting IDs to avoid problems with end_meeting and timeouts
14
15
  * Server administration (modify config.xml, use bbb-conf, etc.)
15
16
 
16
- For more future features and issues check http://code.google.com/p/mconf/issues/list?can=2&q=label%3AComponent%20label%3ABigBlueButtonRails
17
+ For more future features and issues check {our google code page}[http://code.google.com/p/mconf/issues/list?can=2&q=label%3AComponent%20label%3ABigBlueButtonRails].
17
18
 
18
19
  == Installation
19
20
 
@@ -47,7 +48,7 @@ For more information see the section Dependencies below.
47
48
 
48
49
  === Routes
49
50
 
50
- The routes to bigbluebutton_rails can be generated with the helper "bigbluebutton_routes". See the example below:
51
+ The routes to bigbluebutton_rails can be generated with the helper <tt>bigbluebutton_routes</tt>. See the example below:
51
52
 
52
53
  bigbluebutton_routes :default
53
54
 
@@ -72,21 +73,23 @@ So you can allow access to webconference rooms using URLs such as:
72
73
  http://myserver.com/user-10/room-5/join
73
74
  http://myserver.com/zaphod/public-room/join
74
75
 
75
- PS: bigbluebutton_rails does not allows the room access using IDs such as "room-5" or "public-room" yet, but soon you it will.
76
+ Obs: bigbluebutton_rails does not allows the room access using IDs such as "room-5" or "public-room" yet, but soon you it will.
76
77
 
77
78
  === User authorization, permissions and assumptions
78
79
 
79
80
  There are some basic assumptions made by bigbluebutton_rails:
80
81
 
81
- * You have a method called "current_user" that returns the current user;
82
- * The current_user has an attribute or method called "name" that returns his/her fullname.
82
+ * You have a method called <tt>current_user</tt> that returns the current user;
83
+ * The <tt>current_user</tt> has an attribute or method called "name" that returns his/her fullname.
83
84
 
84
85
  If you don't, you can change this behaviour easily, keep reading.
85
86
 
86
- bigbluebutton_rails uses the methods "bigbluebutton_user" and "bigbluebutton_role(room)" to get the current user and to get the permission that the current
87
- user has in the "room", respectively.
87
+ bigbluebutton_rails uses the methods <tt>bigbluebutton_user</tt> and <tt>bigbluebutton_role(room)</tt> to get the current user and to get the permission that the current
88
+ user has in the <tt>room</tt>, respectively. These methods are defined in <tt>lib/bigbluebutton_rails/controller_methods.rb</tt> and you can reimplement them in your
89
+ application controller to change their behaviour.
88
90
 
89
- These methods are defined in "lib/bigbluebutton_rails/controller_methods.rb" and you can reimplement them in your application_controller to change their behaviour.
91
+ Although this is the general rule, the permission checking is different for public or private rooms. Check the <tt>How it Works</tt>
92
+ section below for more details.
90
93
 
91
94
 
92
95
  ==== Integration with Devise
@@ -105,32 +108,62 @@ Files:
105
108
 
106
109
  * Javascripts:
107
110
  * JQuery (jquery.min.js). See http://jquery.com
108
- * JQuery Heartbeat plugin (heartbeat.js). See http://plugins.jquery.com/project/Heartbeat
109
111
  * Images:
110
112
  * loading.gif
111
113
 
112
- All these files are used by views/bigbluebutton/rooms/join_wait and can be generated with:
114
+ JQuery is used in the views <tt>join_wait</tt> and <tt>invite</tt> and can be copied into your application with:
113
115
 
114
116
  rails generate bigbluebutton_rails:public
115
117
 
116
118
  == How it works
117
119
 
120
+ === Overview
121
+
118
122
  bigbluebutton_rails has two entities: servers and rooms. Servers can have multiple rooms, that belong to a server and can also belong to any other model.
119
123
  You can make a room belong to a user, for example.
120
124
 
121
- Every server has an associated API object (using the gem bigbluebutton-api-ruby) used to access BigBlueButton.
122
- The server now has basically the RESTful actions defined in Rails.
125
+ Every server has an associated API object (using the gem bigbluebutton-api-ruby) used to access the BigBlueButton server.
126
+ The server controller has only the standard CRUD actions defined by Rails.
127
+
128
+ The rooms controller also have the CRUD actions, plus some specific actions to join, end, and check if a meeting is currently running in the room.
129
+ These extra actions will be explained bellow.
130
+
131
+ A room model has methods to fetch and send information to the BBB server. They are simple API calls, but the "fetch" methods check the response and store
132
+ data from it, while the "send" methods just make the API call. You can, for example, use <tt>fetch_meeting_info</tt> to get information about the meeting
133
+ (will trigger the API call <tt>getMeetingInfo</tt>). The data parsed from the response wil be stored in the model and can be accessed using it's attributes.
134
+
135
+ All methods in the models that trigger any API call are documented with "Triggers API call" and the API functions that are called. Be aware that they
136
+ can throw a BigBlueButtonException.
137
+
138
+ === RoomsController
139
+
140
+ ==== <tt>running</tt> and <tt>end</tt>
123
141
 
124
- The rooms also have the RESTful actions, plus specific actions to "join", "end", and check if a meeting is being held currently in the room ("running").
125
- All actions are pretty simple. "running" returns a json indicating if the conference is running or not and "end" ends the meeting.
126
- The most elaborated action is "join", that does the following:
142
+ These are pretty simple actions. <tt>running</tt> returns a json indicating if the conference is running or not, while <tt>end</tt> ends the meeting.
143
+
144
+ ==== <tt>join</tt>, <tt>invite</tt> and <tt>auth</tt>
145
+
146
+ The actions used to redirect a user to join a room are <tt>join</tt> and <tt>invite</tt>, while <tt>auth</tt> is used by <tt>invite</tt> to authenticate
147
+ the user. Basic differences:
148
+
149
+ * <tt>invite</tt> renders a view to ask for a user name and a password. It is used to enable <b>anonymous users</b> to join a room or
150
+ to define the user role using the <b>room password</b> instead of the <tt>bigbluebutton_role</tt> method.
151
+ * It first checks <tt>bigbluebutton_role</tt> to see if the current user already has a role in the target room. In case it has, redirects to <tt>join</tt>.
152
+ * If there is a user logged, uses <tt>bigbluebutton_user().name</tt> as the user name. Otherwise, ask the user to type a name.
153
+ * <tt>join</tt> requires a <b>logged user</b> and uses <tt>bigbluebutton_role</tt> to get the role of this user.
154
+ * It redirects the user straight to the meeting if the join is successful.
155
+ * In case there's no role associated with the current user, falls back to <tt>invite</tt> to ask for a password.
156
+
157
+ Internally, they use the same algorithm:
127
158
 
128
159
  * If the user is a moderator:
129
- * If the rooms is not created yet, creates it.
130
- * Redirects to the url to join as a moderator.
160
+ * If the room is not created yet, creates it.
161
+ * Redirects the user to the meeting as a moderator.
131
162
  * If the user is a normal attendee:
132
- * If the rooms is running, redirects to the url to join as an attendee.
133
- * Otherwise, redirects to join_wait, to wait for a moderator before joining the conference.
163
+ * If the meeting is running, redirects the user to the meeting as an attendee.
164
+ * Otherwise:
165
+ * <tt>join</tt> redirects to <tt>join_wait</tt>, to wait for a moderator before joining the conference.
166
+ * <tt>invite</tt> renders the invite view again and shows a warning that the metting is not running.
134
167
 
135
168
  == Development
136
169
 
@@ -144,4 +177,6 @@ Prepare the rails_app used for tests:
144
177
 
145
178
  Run the tests:
146
179
 
147
- rake spec
180
+ rake spec
181
+
182
+ Develop. :)
data/Rakefile CHANGED
@@ -16,6 +16,7 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
16
16
  rdoc.rdoc_files.include('README.rdoc')
17
17
  rdoc.rdoc_files.include('CHANGELOG.rdoc')
18
18
  rdoc.rdoc_files.include('lib/**/*.rb')
19
+ rdoc.rdoc_files.include('app/**/*.rb')
19
20
  end
20
21
 
21
22
  eval("$specification = begin; #{ IO.read('bigbluebutton_rails.gemspec')}; end")
@@ -26,21 +26,29 @@ class Bigbluebutton::RoomsController < ApplicationController
26
26
  def create
27
27
  @room = BigbluebuttonRoom.new(params[:bigbluebutton_room])
28
28
  @room.server = @server
29
-
30
- # TODO Generate a random meeting_id everytime a room is created
31
- if !params[:bigbluebutton_room].has_key?(:meeting_id) or
32
- params[:bigbluebutton_room][:meeting_id].blank?
33
- @room.meeting_id = @room.name
29
+
30
+ # TODO Generate a random meetingid everytime a room is created
31
+ if !params[:bigbluebutton_room].has_key?(:meetingid) or
32
+ params[:bigbluebutton_room][:meetingid].blank?
33
+ @room.meetingid = @room.name
34
34
  end
35
35
 
36
36
  respond_with @room do |format|
37
37
  if @room.save
38
38
  format.html {
39
39
  message = t('bigbluebutton_rails.rooms.notice.create.success')
40
- redirect_to(bigbluebutton_server_room_path(@server, @room), :notice => message)
40
+ params[:redir_url] ||= bigbluebutton_server_room_path(@server, @room)
41
+ redirect_to params[:redir_url], :notice => message
41
42
  }
42
43
  else
43
- format.html { render :action => "new" }
44
+ format.html {
45
+ unless params[:redir_url].blank?
46
+ message = t('bigbluebutton_rails.rooms.notice.create.failure')
47
+ redirect_to params[:redir_url], :error => message
48
+ else
49
+ render :action => "new"
50
+ end
51
+ }
44
52
  end
45
53
  end
46
54
  end
@@ -48,19 +56,27 @@ class Bigbluebutton::RoomsController < ApplicationController
48
56
  def update
49
57
  @room = BigbluebuttonRoom.find(params[:id])
50
58
 
51
- if !params[:bigbluebutton_room].has_key?(:meeting_id) or
52
- params[:bigbluebutton_room][:meeting_id].blank?
53
- params[:bigbluebutton_room][:meeting_id] = params[:bigbluebutton_room][:name]
59
+ if !params[:bigbluebutton_room].has_key?(:meetingid) or
60
+ params[:bigbluebutton_room][:meetingid].blank?
61
+ params[:bigbluebutton_room][:meetingid] = params[:bigbluebutton_room][:name]
54
62
  end
55
63
 
56
64
  respond_with @room do |format|
57
65
  if @room.update_attributes(params[:bigbluebutton_room])
58
66
  format.html {
59
67
  message = t('bigbluebutton_rails.rooms.notice.update.success')
60
- redirect_to(bigbluebutton_server_room_path(@server, @room), :notice => message)
68
+ params[:redir_url] ||= bigbluebutton_server_room_path(@server, @room)
69
+ redirect_to params[:redir_url], :notice => message
61
70
  }
62
71
  else
63
- format.html { render :action => "edit" }
72
+ format.html {
73
+ unless params[:redir_url].blank?
74
+ message = t('bigbluebutton_rails.rooms.notice.update.failure')
75
+ redirect_to params[:redir_url], :error => message
76
+ else
77
+ render :action => "edit"
78
+ end
79
+ }
64
80
  end
65
81
  end
66
82
  end
@@ -79,42 +95,54 @@ class Bigbluebutton::RoomsController < ApplicationController
79
95
  end
80
96
 
81
97
  @room.destroy
82
- redirect_to(bigbluebutton_server_rooms_url)
98
+ params[:redir_url] ||= bigbluebutton_server_rooms_url
99
+ redirect_to params[:redir_url]
83
100
  end
84
101
 
102
+ # Used to join public rooms with a logged user.
85
103
  def join
86
104
  @room = BigbluebuttonRoom.find(params[:id])
105
+
106
+ # anonymous users or users without a role join through #invite
87
107
  role = bigbluebutton_role(@room)
108
+ if bigbluebutton_user.nil? or role.nil?
109
+ redirect_to :action => :invite
110
+ else
111
+ join_internal(bigbluebutton_user.name, role, :join)
112
+ end
88
113
 
89
- begin
90
- @room.fetch_is_running?
114
+ end
91
115
 
92
- # if the current user is a moderator, create the room (if needed)
93
- # and join it
94
- if role == :moderator
95
- @room.send_create unless @room.is_running?
96
- join_url = @room.join_url(bigbluebutton_user.name, role)
97
- redirect_to(join_url)
116
+ # Used to join private rooms or to invited anonymous users (not logged)
117
+ def invite
118
+ @room = BigbluebuttonRoom.find(params[:id])
98
119
 
99
- # normal user only joins if the conference is running
100
- # if it's not, wait for a moderator to create the conference
120
+ respond_with @room do |format|
121
+
122
+ # if there's already a logged user with a role in the room, join through #join
123
+ unless bigbluebutton_user.nil? or bigbluebutton_role(@room).nil?
124
+ format.html { redirect_to :action => :join }
101
125
  else
102
- if @room.is_running?
103
- join_url = @room.join_url(bigbluebutton_user.name, role)
104
- redirect_to(join_url)
105
- else
106
- render :action => :join_wait
107
- end
126
+ format.html
108
127
  end
109
128
 
110
- rescue BigBlueButton::BigBlueButtonException => e
111
- flash[:error] = e.to_s
112
- redirect_to request.referer
113
129
  end
114
-
115
130
  end
116
131
 
117
- def join_wait
132
+ # Authenticates an user using name and password passed in the params from #invite
133
+ def auth
134
+ @room = BigbluebuttonRoom.find(params[:id])
135
+
136
+ # if there's a user logged, use his name instead of the name in the params
137
+ name = bigbluebutton_user.nil? ? params[:user][:name] : bigbluebutton_user.name
138
+ role = @room.user_role(params[:user])
139
+
140
+ unless role.nil? or name.nil?
141
+ join_internal(name, role, :invite)
142
+ else
143
+ flash[:error] = t('bigbluebutton_rails.rooms.error.auth.failure')
144
+ render :action => "invite", :status => :unauthorized
145
+ end
118
146
  end
119
147
 
120
148
  def running
@@ -125,7 +153,6 @@ class Bigbluebutton::RoomsController < ApplicationController
125
153
  rescue BigBlueButton::BigBlueButtonException => e
126
154
  flash[:error] = e.to_s
127
155
  render :json => { running: "false", error: "#{e.to_s}" }
128
- #redirect_to request.referer
129
156
  else
130
157
  render :json => { running: "#{@room.is_running?}" }
131
158
  end
@@ -162,4 +189,34 @@ class Bigbluebutton::RoomsController < ApplicationController
162
189
  end
163
190
  end
164
191
 
192
+ def join_internal(username, role, wait_action)
193
+
194
+ begin
195
+ @room.fetch_is_running?
196
+
197
+ # if the current user is a moderator, create the room (if needed)
198
+ # and join it
199
+ if role == :moderator
200
+ @room.send_create unless @room.is_running?
201
+ join_url = @room.join_url(username, role)
202
+ redirect_to(join_url)
203
+
204
+ # normal user only joins if the conference is running
205
+ # if it's not, wait for a moderator to create the conference
206
+ else
207
+ if @room.is_running?
208
+ join_url = @room.join_url(username, role)
209
+ redirect_to(join_url)
210
+ else
211
+ flash[:error] = t('bigbluebutton_rails.rooms.error.not_running')
212
+ render :action => wait_action
213
+ end
214
+ end
215
+
216
+ rescue BigBlueButton::BigBlueButtonException => e
217
+ flash[:error] = e.to_s
218
+ redirect_to request.referer
219
+ end
220
+ end
221
+
165
222
  end
@@ -1,38 +1,63 @@
1
+ require 'active_support/secure_random'
2
+
1
3
  class BigbluebuttonRoom < ActiveRecord::Base
2
4
  belongs_to :server, :class_name => 'BigbluebuttonServer'
3
5
  belongs_to :owner, :polymorphic => true
4
6
 
5
7
  validates :server_id, :presence => true
6
- validates :meeting_id, :presence => true, :uniqueness => true,
8
+ validates :meetingid, :presence => true, :uniqueness => true,
7
9
  :length => { :minimum => 1, :maximum => 100 }
8
10
  validates :name, :presence => true, :uniqueness => true,
9
11
  :length => { :minimum => 1, :maximum => 150 }
10
- validates :attendee_password, :length => { :maximum => 50 }
11
- validates :moderator_password, :length => { :maximum => 50 }
12
12
  validates :welcome_msg, :length => { :maximum => 250 }
13
+ validates :private, :inclusion => { :in => [true, false] }
14
+ validates :randomize_meetingid, :inclusion => { :in => [true, false] }
15
+
16
+ # Passwords are 16 character strings
17
+ # See http://groups.google.com/group/bigbluebutton-dev/browse_thread/thread/9be5aae1648bcab?pli=1
18
+ validates :attendee_password, :length => { :maximum => 16 }
19
+ validates :moderator_password, :length => { :maximum => 16 }
13
20
 
14
- attr_accessible :name, :server_id, :meeting_id, :attendee_password,
15
- :moderator_password, :welcome_msg, :owner, :server
21
+ attr_accessible :name, :server_id, :meetingid, :attendee_password, :moderator_password,
22
+ :welcome_msg, :owner, :server, :private, :logout_url, :dial_number,
23
+ :voice_bridge, :max_participants, :owner_id, :owner_type, :randomize_meetingid
16
24
 
17
- # Note: these params need to be fetched before being accessed
18
- attr_reader :running, :participant_count, :moderator_count, :attendees,
19
- :has_been_forcibly_ended, :start_time, :end_time
25
+ # Note: these params need to be fetched from the server before being accessed
26
+ attr_accessor :running, :participant_count, :moderator_count, :attendees,
27
+ :has_been_forcibly_ended, :start_time, :end_time
20
28
 
29
+ after_initialize :init
30
+
31
+ # Convenience method to access the attribute <tt>running</tt>
21
32
  def is_running?
22
33
  @running
23
34
  end
24
35
 
36
+ # Fetches info from BBB about this room.
37
+ # The response is parsed and stored in the model. You can access it using attributes such as:
38
+ #
39
+ # room.participant_count
40
+ # room.attendees[0].full_name
41
+ #
42
+ # The attributes changed are:
43
+ # * <tt>participant_count</tt>
44
+ # * <tt>moderator_count</tt>
45
+ # * <tt>running</tt>
46
+ # * <tt>has_been_forcibly_ended</tt>
47
+ # * <tt>start_time</tt>
48
+ # * <tt>end_time</tt>
49
+ # * <tt>attendees</tt> (array of <tt>BigbluebuttonAttendee</tt>)
50
+ #
51
+ # Triggers API call: <tt>get_meeting_info</tt>.
25
52
  def fetch_meeting_info
26
- response = self.server.api.get_meeting_info(self.meeting_id, self.moderator_password)
53
+ response = self.server.api.get_meeting_info(self.meetingid, self.moderator_password)
27
54
 
28
55
  @participant_count = response[:participantCount]
29
56
  @moderator_count = response[:moderatorCount]
30
- @running = response[:running].downcase == "true"
31
- @has_been_forcibly_ended = response[:hasBeenForciblyEnded].downcase == "true"
32
- @start_time = response[:startTime] == "null" ?
33
- nil : DateTime.parse(response[:startTime])
34
- @end_time = response[:endTime] == "null" ?
35
- nil : DateTime.parse(response[:endTime])
57
+ @running = response[:running]
58
+ @has_been_forcibly_ended = response[:hasBeenForciblyEnded]
59
+ @start_time = response[:startTime]
60
+ @end_time = response[:endTime]
36
61
  @attendees = []
37
62
  response[:attendees].each do |att|
38
63
  attendee = BigbluebuttonAttendee.new
@@ -43,37 +68,121 @@ class BigbluebuttonRoom < ActiveRecord::Base
43
68
  response
44
69
  end
45
70
 
71
+ # Fetches the BBB server to see if the meeting is running. Sets <tt>running</tt>
72
+ #
73
+ # Triggers API call: <tt>is_meeting_running</tt>.
46
74
  def fetch_is_running?
47
- @running = self.server.api.is_meeting_running?(self.meeting_id)
75
+ @running = self.server.api.is_meeting_running?(self.meetingid)
48
76
  end
49
77
 
78
+ # Sends a call to the BBB server to end the meeting.
79
+ #
80
+ # Triggers API call: <tt>end_meeting</tt>.
50
81
  def send_end
51
- self.server.api.end_meeting(self.meeting_id, self.moderator_password)
82
+ self.server.api.end_meeting(self.meetingid, self.moderator_password)
52
83
  end
53
84
 
85
+ # Sends a call to the BBB server to create the meeting.
86
+ #
87
+ # With the response, updates the following attributes:
88
+ # * <tt>attendee_password</tt>
89
+ # * <tt>moderator_password</tt>
90
+ #
91
+ # Triggers API call: <tt>create_meeting</tt>.
54
92
  def send_create
55
- response = self.server.api.create_meeting(self.name, self.meeting_id, self.moderator_password,
56
- self.attendee_password, self.welcome_msg)
57
93
 
58
- # updates model information with data returned by BBB
94
+ unless self.randomize_meetingid
95
+ response = do_create_meeting
96
+
97
+ # create a new random meetingid everytime create fails with "duplicateWarning"
98
+ else
99
+ self.meetingid = random_meetingid
100
+
101
+ count = 0
102
+ try_again = true
103
+ while try_again and count < 10
104
+ response = do_create_meeting
105
+
106
+ count += 1
107
+ try_again = false
108
+ unless response.nil?
109
+ if response[:returncode] && response[:messageKey] == "duplicateWarning"
110
+ self.meetingid = random_meetingid
111
+ try_again = true
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
59
118
  unless response.nil?
60
- self.attendee_password = response[:attendeePW].to_s
61
- self.moderator_password = response[:moderatorPW].to_s
119
+ self.attendee_password = response[:attendeePW]
120
+ self.moderator_password = response[:moderatorPW]
62
121
  self.save
63
122
  end
64
123
 
65
124
  response
66
125
  end
67
126
 
68
- # uses the API but does not require a request to the server
127
+ # Returns the URL to join this room.
128
+ # username:: Name of the user
129
+ # role:: Role of the user in this room. Can be <tt>[:moderator, :attendee]</tt>
130
+ #
131
+ # Uses the API but does not require a request to the server.
69
132
  def join_url(username, role)
70
133
  if role == :moderator
71
- self.server.api.join_meeting_url(self.meeting_id, username,
72
- self.moderator_password)
134
+ self.server.api.join_meeting_url(self.meetingid, username, self.moderator_password)
73
135
  else
74
- self.server.api.join_meeting_url(self.meeting_id, username,
75
- self.attendee_password)
136
+ self.server.api.join_meeting_url(self.meetingid, username, self.attendee_password)
76
137
  end
77
138
  end
78
139
 
140
+
141
+ # Returns the role of the user based on the password given.
142
+ # The return value can be <tt>:moderator</tt>, <tt>:attendee</tt>, or
143
+ # nil if the password given does not match any of the room passwords.
144
+ # params:: Hash with a key :password
145
+ def user_role(params)
146
+ role = nil
147
+ if params.has_key?(:password)
148
+ if self.moderator_password == params[:password]
149
+ role = :moderator
150
+ elsif self.attendee_password == params[:password]
151
+ role = :attendee
152
+ end
153
+ end
154
+ role
155
+ end
156
+
157
+ protected
158
+
159
+ def init
160
+ self[:meetingid] ||= random_meetingid
161
+
162
+ # fetched attributes
163
+ @participant_count = 0
164
+ @moderator_count = 0
165
+ @running = false
166
+ @has_been_forcibly_ended = false
167
+ @start_time = nil
168
+ @end_time = nil
169
+ @attendees = []
170
+ end
171
+
172
+ def random_meetingid
173
+ #ActiveSupport::SecureRandom.hex(16)
174
+ # TODO temporarily using the name to get a friendlier meetingid
175
+ if self[:name].blank?
176
+ ActiveSupport::SecureRandom.hex(8)
177
+ else
178
+ self[:name] + '-' + ActiveSupport::SecureRandom.random_number(9999).to_s
179
+ end
180
+ end
181
+
182
+ def do_create_meeting
183
+ self.server.api.create_meeting(self.name, self.meetingid, self.moderator_password,
184
+ self.attendee_password, self.welcome_msg, self.dial_number,
185
+ self.logout_url, self.max_participants, self.voice_bridge)
186
+ end
187
+
79
188
  end
@@ -14,6 +14,8 @@ class BigbluebuttonServer < ActiveRecord::Base
14
14
 
15
15
  validates :version, :presence => true, :inclusion => { :in => ['0.64', '0.7'] }
16
16
 
17
+ # Returns the API object (<tt>BigBlueButton::BigBlueButtonAPI</tt> defined in
18
+ # <tt>bigbluebutton-api-ruby</tt>) associated with this server.
17
19
  def api
18
20
  if @api.nil?
19
21
  @api = BigBlueButton::BigBlueButtonApi.new(self.url, self.salt,
@@ -22,20 +24,34 @@ class BigbluebuttonServer < ActiveRecord::Base
22
24
  @api
23
25
  end
24
26
 
27
+ # Array of <tt>BigbluebuttonMeeting</tt>
25
28
  attr_reader :meetings
26
29
 
30
+ # Fetches the meetings currently created in the server (running or not).
31
+ #
32
+ # Using the response, updates <tt>meetings</tt> with a list of <tt>BigbluebuttonMeeting</tt>
33
+ # objects.
34
+ #
35
+ # Triggers API call: <tt>get_meetings</tt>.
27
36
  def fetch_meetings
28
37
  response = self.api.get_meetings
29
38
 
30
39
  # updates the information in the rooms that are currently in BBB
31
40
  @meetings = []
32
41
  response[:meetings].each do |attr|
33
- room = BigbluebuttonRoom.find_by_server_id_and_meeting_id(self.id, attr[:meetingID])
34
-
35
- meeting = BigbluebuttonMeeting.new
36
- meeting.from_hash(attr)
37
- meeting.room = room
38
- @meetings << meeting
42
+ room = BigbluebuttonRoom.find_by_server_id_and_meetingid(self.id, attr[:meetingID])
43
+ if room.nil?
44
+ room = BigbluebuttonRoom.new(:server => self, :meetingid => attr[:meetingID],
45
+ :attendee_password => attr[:attendeePW],
46
+ :moderator_password => attr[:moderatorPW])
47
+ room.running = attr[:running]
48
+ else
49
+ room.update_attributes(:attendee_password => attr[:attendeePW],
50
+ :moderator_password => attr[:moderatorPW])
51
+ room.running = attr[:running]
52
+ end
53
+
54
+ @meetings << room
39
55
  end
40
56
  end
41
57