bigbluebutton_rails 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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