Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GRN2-199: Allow room owners to set a password that is required to join a room #646

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions app/assets/javascripts/room.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ $(document).on('turbolinks:load', function(){
// Display and update all fields related to creating a room in the createRoomModal
$("#create-room-block").click(function(){
$("#create-room-name").val("")
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
$("#room_access_code").val(null)

$("#createRoomModal form").attr("action", $("body").data('relative-root'))
updateDropdown($(".dropdown-item[value='default']"))
$("#room_mute_on_join").prop("checked", false)
Expand Down Expand Up @@ -80,6 +83,16 @@ $(document).on('turbolinks:load', function(){
})

updateCurrentSettings($(this).closest("#room-block").data("room-settings"))

accessCode = $(this).closest("#room-block").data("room-access-code")

if(accessCode){
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code") %>: " + accessCode)
$("#room_access_code").val(accessCode)
} else{
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
$("#room_access_code").val(null)
}
})

//Update the createRoomModal to show the correct current settings
Expand Down Expand Up @@ -107,3 +120,21 @@ function updateDropdown(element) {
$("#dropdown-trigger").text(element.text())
$("#room_client").val(element.val())
}

function generateAccessCode(){
const accessCodeLength = 6
var validCharacters = "0123456789"
var accessCode = ""

for( var i = 0; i < accessCodeLength; i++){
accessCode += validCharacters.charAt(Math.floor(Math.random() * validCharacters.length));
}

$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code") %>: " + accessCode)
$("#room_access_code").val(accessCode)
}

function ResetAccessCode(){
$("#create-room-access-code").text("<%= I18n.t("modal.create_room.access_code_placeholder") %>")
$("#room_access_code").val(null)
}
4 changes: 4 additions & 0 deletions app/assets/stylesheets/rooms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@
background-color: rgba(0, 0, 0, 0.04);
}
}

.allow-icon-click{
pointer-events: auto;
}
78 changes: 50 additions & 28 deletions app/controllers/rooms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class RoomsController < ApplicationController
before_action :validate_verified_email, except: [:show, :join],
unless: -> { !Rails.configuration.enable_email_verification }
before_action :find_room, except: :create
before_action :verify_room_ownership, except: [:create, :show, :join, :logout]
before_action :verify_room_ownership, except: [:create, :show, :join, :logout, :login]
before_action :verify_room_owner_verified, only: [:show, :join],
unless: -> { !Rails.configuration.enable_email_verification }
before_action :verify_user_not_admin, only: [:show]
Expand All @@ -36,7 +36,7 @@ def create

return redirect_to current_user.main_room, flash: { alert: I18n.t("room.room_limit") } if room_limit_exceeded

@room = Room.new(name: room_params[:name])
@room = Room.new(name: room_params[:name], access_code: room_params[:access_code])
@room.owner = current_user
@room.room_settings = create_room_settings_string(room_params[:mute_on_join], room_params[:client])

Expand Down Expand Up @@ -106,6 +106,12 @@ def join

opts = default_meeting_options
unless @room.owned_by?(current_user)
# Don't allow users to join unless they have a valid access code or the room doesn't
# have an access code
if @room.access_code && !@room.access_code.empty? && @room.access_code != session[:access_code]
return redirect_to room_path(room_uid: params[:room_uid]), flash: { alert: I18n.t("room.access_code_required") }
end

# Assign join name if passed.
if params[@room.invite_path]
@join_name = params[@room.invite_path][:join_name]
Expand All @@ -118,31 +124,7 @@ def join
# create or update cookie with join name
cookies.encrypted[:greenlight_name] = @join_name unless cookies.encrypted[:greenlight_name] == @join_name

if @room.running? || @room.owned_by?(current_user)
# Determine if the user needs to join as a moderator.
opts[:user_is_moderator] = @room.owned_by?(current_user)

# Check if the user has specified which client to use
room_settings = JSON.parse(@room[:room_settings])
opts[:join_via_html5] = room_settings["joinViaHtml5"] if room_settings["joinViaHtml5"]

if current_user
redirect_to @room.join_path(current_user.name, opts, current_user.uid)
else
join_name = params[:join_name] || params[@room.invite_path][:join_name]
redirect_to @room.join_path(join_name, opts)
end
else

search_params = params[@room.invite_path] || params
@search, @order_column, @order_direction, pub_recs =
public_recordings(@room.bbb_id, @user_domain, search_params.permit(:search, :column, :direction), true)

@pagy, @public_recordings = pagy_array(pub_recs)

# They need to wait until the meeting begins.
render :wait
end
join_room(opts)
end

# DELETE /:room_uid
Expand Down Expand Up @@ -185,6 +167,8 @@ def update_settings
update_room_attributes("settings")
# Update the rooms name if it has been changed
update_room_attributes("name") if @room.name != room_params[:name]
# Update the room's access code if it has changed
update_room_attributes("access_code") if @room.access_code != room_params[:access_code]
rescue StandardError
flash[:alert] = I18n.t("room.update_settings_error")
else
Expand All @@ -199,6 +183,15 @@ def logout
redirect_to @room
end

# POST /:room_uid/login
def login
session[:access_code] = room_params[:access_code]

flash[:alert] = I18n.t("room.access_code_required") if session[:access_code] != @room.access_code

redirect_to room_path(@room.uid)
end

private

def update_room_attributes(update_type)
Expand All @@ -208,6 +201,8 @@ def update_room_attributes(update_type)
elsif update_type.eql? "settings"
room_settings_string = create_room_settings_string(room_params[:mute_on_join], room_params[:client])
@room.update_attributes(room_settings: room_settings_string)
elsif update_type.eql? "access_code"
@room.update_attributes(access_code: room_params[:access_code])
end
end
end
Expand All @@ -226,7 +221,7 @@ def create_room_settings_string(mute_res, client_res)
end

def room_params
params.require(:room).permit(:name, :auto_join, :mute_on_join, :client)
params.require(:room).permit(:name, :auto_join, :mute_on_join, :client, :access_code)
end

# Find the room from the uid.
Expand Down Expand Up @@ -292,4 +287,31 @@ def room_limit_exceeded

current_user.rooms.count >= limit
end

def join_room(opts)
if @room.running? || @room.owned_by?(current_user)
# Determine if the user needs to join as a moderator.
opts[:user_is_moderator] = @room.owned_by?(current_user)

# Check if the user has specified which client to use
room_settings = JSON.parse(@room[:room_settings])
opts[:join_via_html5] = room_settings["joinViaHtml5"] if room_settings["joinViaHtml5"]

if current_user
redirect_to @room.join_path(current_user.name, opts, current_user.uid)
else
join_name = params[:join_name] || params[@room.invite_path][:join_name]
redirect_to @room.join_path(join_name, opts)
end
else
search_params = params[@room.invite_path] || params
@search, @order_column, @order_direction, pub_recs =
public_recordings(@room.bbb_id, @user_domain, search_params.permit(:search, :column, :direction), true)

@pagy, @public_recordings = pagy_array(pub_recs)

# They need to wait until the meeting begins.
render :wait
end
end
end
14 changes: 13 additions & 1 deletion app/views/rooms/join.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,21 @@
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>

<%= render 'shared/room_event' do %>
<% valid_access_code = @room.access_code.nil? || @room.access_code.empty? || @room.access_code == session[:access_code] %>
<%= render 'shared/room_event', render_recordings: valid_access_code do %>
<% if room_authentication_required %>
<h2><%= t("administrator.site_settings.authentication.user-info") %></h2>
<% elsif !valid_access_code %>
<%= form_for :room, url: login_room_path(@room.uid) do |f| %>
<div class="input-group join-input">
<%= f.text_field :access_code,
required: true,
class: "form-control join-form",
placeholder: t("room.enter_the_access_code"),
value: "" %>
<%= f.submit t("room.login"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %>
</div>
<% end %>
<% else %>
<%= form_for room_path(@room), method: :post do |f| %>
<div class="input-group join-input">
Expand Down
2 changes: 1 addition & 1 deletion app/views/rooms/wait.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>

<%= render 'shared/room_event' do %>
<%= render 'shared/room_event', render_recordings: true do %>
<div class="row">
<div class="col-9">
<h3><%= t("room.wait.message") %></h3>
Expand Down
4 changes: 3 additions & 1 deletion app/views/shared/_room_event.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@
</div>
</div>

<%= render "shared/sessions", recordings: @public_recordings, pagy: @pagy, only_public: true, user_recordings: false, title: t("room.recordings") %>
<% if render_recordings %>
<%= render "shared/sessions", recordings: @public_recordings, pagy: @pagy, only_public: true, user_recordings: false, title: t("room.recordings") %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/shared/components/_room_block.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>

<div id="<%= if room == current_user.main_room then 'home_room_block' else 'room-block' end %>" data-room-uid="<%= room.uid %>" data-room-settings=<%= room.room_settings %> class="card">
<div id="<%= if room == current_user.main_room then 'home_room_block' else 'room-block' end %>" data-room-uid="<%= room.uid %>" data-room-settings=<%= room.room_settings %> data-room-access-code="<%= room.access_code %>" class="card">
<div class="card-body p-1">
<table class="table table-hover table-vcenter text-wrap table-no-border">
<tbody class="no-border-top">
Expand Down
13 changes: 12 additions & 1 deletion app/views/shared/modals/_create_room_modal.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,21 @@
<span class="input-icon-addon">
<i class="fas fa-chalkboard-teacher"></i>
</span>
<%= f.text_field :name, id: "create-room-name", class: "form-control", value: "", placeholder: t("modal.create_room.name_placeholder"), autocomplete: :off %>
<%= f.text_field :name, id: "create-room-name", class: "form-control text-center", value: "", placeholder: t("modal.create_room.name_placeholder"), autocomplete: :off %>
<div class="invalid-feedback text-left"><%= t("modal.create_room.not_blank") %></div>
</div>

<div class="input-icon mb-2">
<span onclick="generateAccessCode()" class="input-icon-addon allow-icon-click">
<i class="fas fa-dice"></i>
</span>
<%= f.label :access_code, t("modal.create_room.access_code_placeholder"), id: "create-room-access-code", class: "form-control" %>
<%= f.hidden_field :access_code %>
<span onclick="ResetAccessCode()" class="input-icon-addon allow-icon-click">
<i class="far fa-trash-alt"></i>
</span>
</div>

<% if Rails.configuration.room_features.include? "default-client" %>
<label class="mt-3 mb-3 w-100 text-left d-inline-block">
<input type="hidden" name="room[client]" id="room_client">
Expand Down
5 changes: 5 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ en:
max_concurrent: The maximum number of concurrent sessions allowed has been reached!
modal:
create_room:
access_code: Access Code
access_code_placeholder: Generate an optional room access code
auto_join: Automatically join me into the room
create: Create Room
free_delete: You will be free to delete this room at any time.
Expand Down Expand Up @@ -357,13 +359,16 @@ en:
super_admin: Super Admin
user: User
room:
access_code_required: Please enter a valid access code to join the room
create_room: Create a Room
create_room_error: There was an error creating the room
create_room_success: Room created successfully
enter_the_access_code: Enter the room's access code
invited: You have been invited to join
invite_participants: Invite Participants
join: Join
last_session: Last session on %{session}
login: Login
owner: Owner
no_sessions: This room has no sessions, yet!
recordings: Room Recordings
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
post '/update_settings', to: 'rooms#update_settings'
post '/start', to: 'rooms#start', as: :start_room
get '/logout', to: 'rooms#logout', as: :logout_room
post '/login', to: 'rooms#login', as: :login_room
end

# Recording operations routes
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20190711192033_add_password_digest_to_rooms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddPasswordDigestToRooms < ActiveRecord::Migration[5.0]
def change
add_column :rooms, :access_code, :string, null: true, default: nil
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20190522195242) do
ActiveRecord::Schema.define(version: 20190711192033) do

create_table "features", force: :cascade do |t|
t.integer "setting_id"
Expand Down Expand Up @@ -56,6 +56,7 @@
t.string "room_settings", default: "{ }"
t.string "moderator_pw"
t.string "attendee_pw"
t.string "access_code"
t.index ["bbb_id"], name: "index_rooms_on_bbb_id"
t.index ["last_session"], name: "index_rooms_on_last_session"
t.index ["name"], name: "index_rooms_on_name"
Expand Down
49 changes: 49 additions & 0 deletions spec/controllers/rooms_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,32 @@ def random_valid_room_params
expect(response).to render_template(:wait)
end

it "should render wait if the correct access code is supplied" do
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(false)

protected_room = Room.new(name: 'test', access_code: "123456")
protected_room.owner = @owner
protected_room.save

@request.session[:user_id] = @user.id
post :join, params: { room_uid: protected_room, join_name: @user.name }, session: { access_code: "123456" }

expect(response).to render_template(:wait)
end

it "should redirect to login if the correct access code isn't supplied" do
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(false)

protected_room = Room.new(name: 'test', access_code: "123456")
protected_room.owner = @owner
protected_room.save

@request.session[:user_id] = @user.id
post :join, params: { room_uid: protected_room, join_name: @user.name }, session: { access_code: "123455" }

expect(response).to redirect_to room_path(protected_room.uid)
end

it "should join owner as moderator if meeting running" do
allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(true)

Expand Down Expand Up @@ -374,4 +400,27 @@ def random_valid_room_params
expect(response).to redirect_to(@room)
end
end

describe "POST #login" do
before do
@user = create(:user)
@room = @user.main_room
@room.access_code = "123456"
@room.save
end

it "should redirect to show with valid access code" do
post :login, params: { room_uid: @room.uid, room: { access_code: "123456" } }

expect(response).to redirect_to room_path(@room.uid)
expect(flash[:alert]).to be_nil
end

it "should redirect to show with and notify user of invalid access code" do
post :login, params: { room_uid: @room.uid, room: { access_code: "123455" } }

expect(response).to redirect_to room_path(@room.uid)
expect(flash[:alert]).to eq(I18n.t("room.access_code_required"))
end
end
end