mirror of https://github.com/dani/vroom.git
Some big changes arround password and authentication handling
This commit is contained in:
parent
b962a9e384
commit
305b6cf5eb
|
@ -127,6 +127,7 @@ our %Lexicon = (
|
|||
"WRONG_PASSWORD" => "Wrong password",
|
||||
"PASSWORD_REQUIRED" => "Password required",
|
||||
"A_PASSWORD_IS_NEEDED_TO_JOIN" => "You must provide a password to join this room",
|
||||
"ROOM_LOCKED_ENTER_OWNER_PASSWORD" => "This room is locked. Only an administrator can joint it. Please enter the administrator's password",
|
||||
"TRY_AGAIN" => "Try again",
|
||||
"AUTH_IF_OWNER" => "Authenticate if you are the room owner",
|
||||
"CREATE_THIS_ROOM" => "Create this room",
|
||||
|
|
|
@ -133,6 +133,7 @@ our %Lexicon = (
|
|||
"WRONG_PASSWORD" => "Mauvais mot de passe",
|
||||
"PASSWORD_REQUIRED" => "Mot de passe requis",
|
||||
"A_PASSWORD_IS_NEEDED_TO_JOIN" => "Vous devez saisir un mot de passe pour rejoindre ce salon",
|
||||
"ROOM_LOCKED_ENTER_OWNER_PASSWORD" => "Ce salon est verrouillé, seul un administrateur peut le rejoindre. Veuillez saisir le mot de passe d'administration du salon",
|
||||
"TRY_AGAIN" => "Essayer à nouveau",
|
||||
"AUTH_IF_OWNER" => "Authentifiez-vous si vous êtes le propriétaire du salon",
|
||||
"CREATE_THIS_ROOM" => "Créez ce salon",
|
||||
|
|
|
@ -32,6 +32,18 @@ var itemPerPage = 20;
|
|||
// Will store the global webrtc object
|
||||
var webrtc = undefined;
|
||||
var roomInfo = {};
|
||||
var peers = {
|
||||
local: {
|
||||
screenShared: false,
|
||||
micMuted: false,
|
||||
videoPaused: false,
|
||||
displayName: '',
|
||||
color: chooseColor(),
|
||||
role: 'participant',
|
||||
hasVideo: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Mark current page link as active
|
||||
$('#lnk_' + page).addClass('active');
|
||||
|
@ -239,6 +251,18 @@ $(document).on('click','button.btn-remove-email',function(e){
|
|||
el.remove();
|
||||
});
|
||||
|
||||
// Update the displayName of the peer
|
||||
// and its screen if any
|
||||
function updateDisplayName(id){
|
||||
// We might receive the screen before the peer itself
|
||||
// so check if the object exists before using it, or fallback with empty values
|
||||
var display = (peers[id] && peers[id].hasName) ? stringEscape(peers[id].displayName) : '';
|
||||
var color = (peers[id] && peers[id].color) ? peers[id].color : chooseColor();
|
||||
var screenName = (peers[id] && peers[id].hasName) ? sprintf(localize('SCREEN_s'), stringEscape(peers[id].displayName)) : '';
|
||||
$('#name_' + id).html(display).css('background-color', color);
|
||||
$('#name_' + id + '_screen').html(screenName).css('background-color', color);
|
||||
}
|
||||
|
||||
// Handle owner/join password confirm
|
||||
$('#ownerPassConfirm').on('input', function() {
|
||||
if ($('#ownerPassConfirm').val() == $('#ownerPass').val() &&
|
||||
|
@ -353,6 +377,47 @@ $('#configureRoomForm').submit(function(e){
|
|||
});
|
||||
});
|
||||
|
||||
// Get our role and other room settings from the server
|
||||
function getRoomInfo(cb){
|
||||
$.ajax({
|
||||
data: {
|
||||
req: JSON.stringify({
|
||||
action: 'get_room_conf',
|
||||
param: {
|
||||
room: roomName,
|
||||
}
|
||||
})
|
||||
},
|
||||
error: function(data){
|
||||
showApiError(data);
|
||||
},
|
||||
success: function(data){
|
||||
roomInfo = data;
|
||||
// Reset the list of email displayed, so first remove evry input field but the last one
|
||||
// We keep it so we can clone it again
|
||||
$('.email-list').find('.email-entry:not(:last)').remove();
|
||||
$.each(data.notif, function(index, obj){
|
||||
addEmailInputField('email-list-notification', obj.email);
|
||||
});
|
||||
// Now, remove the first one if the list is not empty
|
||||
if (Object.keys(data.notif).length > 0){
|
||||
$('.email-list').find('.email-entry:first').remove();
|
||||
}
|
||||
else{
|
||||
$('.email-list').find('.email-entry:first').find('input:first').val('');
|
||||
}
|
||||
adjustAddRemoveEmailButtons();
|
||||
// Update config switches
|
||||
$('#lockedSet').bootstrapSwitch('state', data.locked);
|
||||
$('#askForNameSet').bootstrapSwitch('state', data.ask_for_name);
|
||||
$('#joinPassSet').bootstrapSwitch('state', data.join_auth);
|
||||
$('#ownerPassSet').bootstrapSwitch('state', data.owner_auth);
|
||||
if (typeof cb === 'function'){
|
||||
cb();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Used on the index page
|
||||
function initIndex(){
|
||||
|
@ -667,7 +732,7 @@ function initJoin(room){
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Submit the join password form
|
||||
$('#authBeforeJoinForm').submit(function(event){
|
||||
event.preventDefault();
|
||||
var pass = $('#authBeforeJoinPass').val();
|
||||
|
@ -677,7 +742,41 @@ function initJoin(room){
|
|||
}
|
||||
});
|
||||
|
||||
function try_auth(pass, hideErrorMsg){
|
||||
// This is the displayName input before joining the room
|
||||
$('#displayNamePre').on('input', function() {
|
||||
var name = $('#displayNamePre').val();
|
||||
if (name.length > 0 && name.length < 50){
|
||||
$('#displayNamePreButton').removeClass('disabled');
|
||||
$('#displayNamePre').parent().removeClass('has-error');
|
||||
}
|
||||
else{
|
||||
$('#displayNamePreButton').addClass('disabled');
|
||||
$('#displayNamePre').parent().addClass('has-error');
|
||||
if (name.length < 1){
|
||||
$('#displayNamePre').notify(localize('DISPLAY_NAME_REQUIRED'), 'error');
|
||||
}
|
||||
else{
|
||||
$('#displayNamePre').notify(localize('DISPLAY_NAME_TOO_LONG'), 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#displayNamePreForm').submit(function(event){
|
||||
event.preventDefault();
|
||||
var name = $('#displayNamePre').val();
|
||||
if (name.length > 0 && name.length < 50){
|
||||
$('#display-name-pre').slideUp();
|
||||
$('#displayName').val(name);
|
||||
peers.local.hasName = true;
|
||||
peers.local.displayName = name;
|
||||
updateDisplayName('local');
|
||||
$('#chatBox').removeAttr('disabled').removeAttr('placeholder');
|
||||
init_webrtc(room);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function try_auth(pass, showErrorMsg){
|
||||
$.ajax({
|
||||
data: {
|
||||
req: JSON.stringify({
|
||||
|
@ -689,11 +788,19 @@ function initJoin(room){
|
|||
})
|
||||
},
|
||||
error: function(data){
|
||||
// 401 means password is missing or incorrect
|
||||
// 401 means password is needed
|
||||
if (data.status === 401){
|
||||
data = data.responseJSON;
|
||||
$('.connecting-err-reason').text(data.msg);
|
||||
$('#auth-before-join').slideDown();
|
||||
}
|
||||
if (hideErrorMsg){
|
||||
else if (data.status === 403){
|
||||
data = data.responseJSON;
|
||||
$('.connecting-err-reason').text(data.msg);
|
||||
$('.connecting-msg').not('#room-is-locked').remove();
|
||||
$('#room-is-locked').slideDown();
|
||||
}
|
||||
if (showErrorMsg){
|
||||
showApiError(data);
|
||||
}
|
||||
},
|
||||
|
@ -701,7 +808,7 @@ function initJoin(room){
|
|||
$.ajax({
|
||||
data: {
|
||||
req: JSON.stringify({
|
||||
action: 'get_rtc_conf',
|
||||
action: 'get_room_conf',
|
||||
param: {
|
||||
room: room,
|
||||
}
|
||||
|
@ -711,22 +818,12 @@ function initJoin(room){
|
|||
showApiError(data);
|
||||
},
|
||||
success: function(data){
|
||||
if (!video){
|
||||
data.config.media.video = false;
|
||||
}
|
||||
data.config.localVideoEl = 'webRTCVideoLocal';
|
||||
webrtc = new SimpleWebRTC(data.config);
|
||||
// If browser doesn't support webRTC or dataChannels
|
||||
if (!webrtc.capabilities.support || !webrtc.capabilities.supportGetUserMedia || !webrtc.capabilities.supportDataChannel){
|
||||
$('.connecting-msg').not('#no-webrtc-msg').remove();
|
||||
$('#no-webrtc-msg').slideDown();
|
||||
roomInfo = data;
|
||||
if (roomInfo.ask_for_name){
|
||||
$('#display-name-pre').slideDown();
|
||||
}
|
||||
else{
|
||||
// Hide screen sharing btn if not supported, disable it on mobile
|
||||
if (!webrtc.capabilities.supportScreenSharing || !$.browser.desktop){
|
||||
$('.btn-share-screen').remove();
|
||||
}
|
||||
initVroom(room);
|
||||
init_webrtc(roomName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -736,22 +833,51 @@ function initJoin(room){
|
|||
try_auth('', false);
|
||||
}
|
||||
|
||||
function init_webrtc(room){
|
||||
$.ajax({
|
||||
data: {
|
||||
req: JSON.stringify({
|
||||
action: 'get_rtc_conf',
|
||||
param: {
|
||||
room: room,
|
||||
}
|
||||
})
|
||||
},
|
||||
error: function(data){
|
||||
showApiError(data);
|
||||
},
|
||||
success: function(data){
|
||||
if (!video){
|
||||
data.config.media.video = false;
|
||||
}
|
||||
data.config.localVideoEl = 'webRTCVideoLocal';
|
||||
webrtc = new SimpleWebRTC(data.config);
|
||||
// Handle the readyToCall event: join the room
|
||||
// Or prompt for a name first
|
||||
webrtc.once('readyToCall', function () {
|
||||
peers.local.id = webrtc.connection.connection.socket.sessionid;
|
||||
webrtc.joinRoom(roomName);
|
||||
});
|
||||
|
||||
// If browser doesn't support webRTC or dataChannels
|
||||
if (!webrtc.capabilities.support || !webrtc.capabilities.supportGetUserMedia || !webrtc.capabilities.supportDataChannel){
|
||||
$('.connecting-msg').not('#no-webrtc-msg').remove();
|
||||
$('#no-webrtc-msg').slideDown();
|
||||
}
|
||||
else{
|
||||
// Hide screen sharing btn if not supported, disable it on mobile
|
||||
if (!webrtc.capabilities.supportScreenSharing || !$.browser.desktop){
|
||||
$('.btn-share-screen').remove();
|
||||
}
|
||||
initVroom(room);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// This is the main function called when you join a room
|
||||
function initVroom(room) {
|
||||
|
||||
// This object will be used to record all
|
||||
// the peers and their info. Init with our own info
|
||||
var peers = {
|
||||
local: {
|
||||
screenShared: false,
|
||||
micMuted: false,
|
||||
videoPaused: false,
|
||||
displayName: '',
|
||||
color: chooseColor(),
|
||||
role: 'participant',
|
||||
hasVideo: true
|
||||
}
|
||||
};
|
||||
var mainVid = false,
|
||||
chatHistory = {},
|
||||
chatIndex = 0,
|
||||
|
@ -772,53 +898,6 @@ function initVroom(room) {
|
|||
return count;
|
||||
}
|
||||
|
||||
// Get our role and other room settings from the server
|
||||
function getRoomInfo(ev){
|
||||
$.ajax({
|
||||
data: {
|
||||
req: JSON.stringify({
|
||||
action: 'get_room_conf',
|
||||
param: {
|
||||
room: roomName,
|
||||
}
|
||||
})
|
||||
},
|
||||
error: function(data){
|
||||
showApiError(data);
|
||||
},
|
||||
success: function(data){
|
||||
roomInfo = data;
|
||||
// Reset the list of email displayed, so first remove evry input field but the last one
|
||||
// We keep it so we can clone it again
|
||||
$('.email-list').find('.email-entry:not(:last)').remove();
|
||||
$.each(data.notif, function(index, obj){
|
||||
addEmailInputField('email-list-notification', obj.email);
|
||||
});
|
||||
// Now, remove the first one if the list is not empty
|
||||
if (Object.keys(data.notif).length > 0){
|
||||
$('.email-list').find('.email-entry:first').remove();
|
||||
}
|
||||
else{
|
||||
$('.email-list').find('.email-entry:first').find('input:first').val('');
|
||||
}
|
||||
adjustAddRemoveEmailButtons();
|
||||
// Update config switches
|
||||
$('#lockedSet').bootstrapSwitch('state', data.locked);
|
||||
$('#askForNameSet').bootstrapSwitch('state', data.ask_for_name);
|
||||
$('#joinPassSet').bootstrapSwitch('state', data.join_auth);
|
||||
$('#ownerPassSet').bootstrapSwitch('state', data.owner_auth);
|
||||
if (ev === 'join'){
|
||||
if (data.ask_for_name){
|
||||
$('#display-name-pre').slideDown();
|
||||
}
|
||||
else{
|
||||
webrtc.joinRoom(room);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get the role of a peer
|
||||
function getPeerRole(id){
|
||||
$.ajax({
|
||||
|
@ -1134,18 +1213,6 @@ function initVroom(room) {
|
|||
chatIndex++;
|
||||
}
|
||||
|
||||
// Update the displayName of the peer
|
||||
// and its screen if any
|
||||
function updateDisplayName(id){
|
||||
// We might receive the screen before the peer itself
|
||||
// so check if the object exists before using it, or fallback with empty values
|
||||
var display = (peers[id] && peers[id].hasName) ? stringEscape(peers[id].displayName) : '';
|
||||
var color = (peers[id] && peers[id].color) ? peers[id].color : chooseColor();
|
||||
var screenName = (peers[id] && peers[id].hasName) ? sprintf(localize('SCREEN_s'), stringEscape(peers[id].displayName)) : '';
|
||||
$('#name_' + id).html(display).css('background-color', color);
|
||||
$('#name_' + id + '_screen').html(screenName).css('background-color', color);
|
||||
}
|
||||
|
||||
// Mute a peer
|
||||
function mutePeer(id,globalAction){
|
||||
if (peers[id] && peers[id].role != 'owner'){
|
||||
|
@ -1552,13 +1619,6 @@ function initVroom(room) {
|
|||
getPeerRole(data.id);
|
||||
});
|
||||
|
||||
// Handle the readyToCall event: join the room
|
||||
// Or prompt for a name first
|
||||
webrtc.once('readyToCall', function () {
|
||||
peers.local.id = webrtc.connection.connection.socket.sessionid;
|
||||
getRoomInfo('join');
|
||||
});
|
||||
|
||||
//Notification from the server
|
||||
webrtc.connection.connection.on('notification', function(data) {
|
||||
if (!data.payload.class || !data.payload.class.match(/^(success)|(info)|(warning)|(error)$/)){
|
||||
|
@ -1794,39 +1854,6 @@ function initVroom(room) {
|
|||
}, 3100);
|
||||
}
|
||||
});
|
||||
// This is the displayName input before joining the room
|
||||
$('#displayNamePre').on('input', function() {
|
||||
var name = $('#displayNamePre').val();
|
||||
if (name.length > 0 && name.length < 50){
|
||||
$('#displayNamePreButton').removeClass('disabled');
|
||||
$('#displayNamePre').parent().removeClass('has-error');
|
||||
}
|
||||
else{
|
||||
$('#displayNamePreButton').addClass('disabled');
|
||||
$('#displayNamePre').parent().addClass('has-error');
|
||||
if (name.length < 1){
|
||||
$('#displayNamePre').notify(localize('DISPLAY_NAME_REQUIRED'), 'error');
|
||||
}
|
||||
else{
|
||||
$('#displayNamePre').notify(localize('DISPLAY_NAME_TOO_LONG'), 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#displayNamePreForm').submit(function(event){
|
||||
event.preventDefault();
|
||||
var name = $('#displayNamePre').val();
|
||||
if (name.length > 0 && name.length < 50){
|
||||
//$('#setDisplayName').modal('hide');
|
||||
$('#display-name-pre').slideUp();
|
||||
$('#displayName').val(name);
|
||||
peers.local.hasName = true;
|
||||
peers.local.displayName = name;
|
||||
updateDisplayName('local');
|
||||
$('#chatBox').removeAttr('disabled').removeAttr('placeholder');
|
||||
webrtc.joinRoom(room);
|
||||
}
|
||||
});
|
||||
|
||||
// ScreenSharing
|
||||
$('.btn-share-screen').click(function() {
|
||||
|
|
|
@ -219,6 +219,13 @@
|
|||
<p class="text-center">
|
||||
<%=l 'CONNECTING_PLEASE_WAIT' %>
|
||||
</p>
|
||||
<p class="text-center connecting-err-reason">
|
||||
</p>
|
||||
</div>
|
||||
<div id="room-is-locked" class="connecting-msg" style="display: none">
|
||||
%= image '/img/lock.png', alt => $self->l('LOCKED'), class => "img-responsive center-block"
|
||||
<p class="text-center connecting-err-reason">
|
||||
</p>
|
||||
</div>
|
||||
<div id="no-webcam-msg" class="connecting-msg" style="display: none">
|
||||
<p class="text-center">
|
||||
|
@ -238,9 +245,6 @@
|
|||
</div>
|
||||
<div id="auth-before-join" class="connecting-msg" style="display: none">
|
||||
<form role="form" class="form-horizontal" id="authBeforeJoinForm">
|
||||
<p class="text-center">
|
||||
<%=l 'A_PASSWORD_IS_NEEDED_TO_JOIN' %>
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label for="authBeforJoinPass" class="col-sm-4 control-label">
|
||||
<%=l 'PASSWORD' %>
|
||||
|
|
49
vroom.pl
49
vroom.pl
|
@ -839,7 +839,9 @@ helper get_key_role => sub {
|
|||
$sth->execute($key->{id},$room);
|
||||
$sth->bind_columns(\$key->{role});
|
||||
$sth->fetch;
|
||||
$self->app->log->debug("Key $token has role:" . $key->{role} . " in room $room");
|
||||
if ($key->{role}){
|
||||
$self->app->log->debug("Key $token has role:" . $key->{role} . " in room $room");
|
||||
}
|
||||
return $key->{role};
|
||||
};
|
||||
|
||||
|
@ -975,7 +977,6 @@ helper get_room_conf => sub {
|
|||
# Socket.IO handshake
|
||||
get '/socket.io/:ver' => sub {
|
||||
my $self = shift;
|
||||
$self->session(peer_id => $self->get_random(256));
|
||||
my $handshake = Protocol::SocketIO::Handshake->new(
|
||||
session_id => $self->session('peer_id'),
|
||||
heartbeat_timeout => 20,
|
||||
|
@ -1023,7 +1024,7 @@ websocket '/socket.io/:ver/websocket/:id' => sub {
|
|||
!$self->session($room)->{role} ||
|
||||
$self->session($room)->{role} !~ m/^owner|participant$/){
|
||||
$self->app->log->debug("Failed to connect to the signaling channel, " . $self->session('name') .
|
||||
" (session ID " . $self->session('id') . ") has no role for this room");
|
||||
" (session ID " . $self->session('id') . ") has no role in room $room");
|
||||
$self->send( Protocol::SocketIO::Message->new( type => 'disconnect' ) );
|
||||
$self->finish;
|
||||
return;
|
||||
|
@ -1464,15 +1465,19 @@ any '/api' => sub {
|
|||
# Ok, now, we don't have to bother with authorization anymore
|
||||
if ($req->{action} eq 'authenticate'){
|
||||
my $pass = $req->{param}->{password};
|
||||
# Is this peer already authenticated ?
|
||||
my $role = $self->get_key_role($token, $room->{name});
|
||||
my $reason;
|
||||
my $code = 401;
|
||||
if (!$self->session('peer_id') || $self->session('peer_id') eq ''){
|
||||
$self->session(peer_id => $self->get_random(256));
|
||||
}
|
||||
if ($room->{owner_password} && Crypt::SaltedHash->validate($room->{owner_password}, $pass)){
|
||||
$role = 'owner';
|
||||
}
|
||||
elsif (!$role && $room->{join_password} && Crypt::SaltedHash->validate($room->{join_password}, $pass)){
|
||||
$role = 'participant';
|
||||
}
|
||||
elsif (!$role && !$room->{join_password}){
|
||||
elsif (!$role && !$room->{join_password} && !$room->{locked}){
|
||||
$role = 'participant';
|
||||
}
|
||||
if ($role){
|
||||
|
@ -1492,16 +1497,30 @@ any '/api' => sub {
|
|||
);
|
||||
return $self->render(
|
||||
json => {
|
||||
msg => $self->l('AUTH_SUCCESS'),
|
||||
role => $role
|
||||
msg => $self->l('AUTH_SUCCESS'),
|
||||
role => $role,
|
||||
peer_id => $self->session('peer_id')
|
||||
}
|
||||
);
|
||||
}
|
||||
elsif ($room->{locked} && $room->{owner_password}){
|
||||
$reason = $self->l('ROOM_LOCKED_ENTER_OWNER_PASSWORD');
|
||||
}
|
||||
elsif ($room->{locked}){
|
||||
$reason = sprintf($self->l('ERROR_ROOM_s_LOCKED'), $room->{name});
|
||||
$code = 403;
|
||||
}
|
||||
elsif ((!$pass || $pass eq '') && $room->{join_password}){
|
||||
$reason = $self->l('A_PASSWORD_IS_NEEDED_TO_JOIN')
|
||||
}
|
||||
elsif ($room->{join_password}){
|
||||
$reason = $self->l('WRONG_PASSWORD');
|
||||
}
|
||||
return $self->render(
|
||||
json => {
|
||||
msg => $self->l('WRONG_PASSWORD')
|
||||
msg => $reason
|
||||
},
|
||||
status => '401'
|
||||
status => $code
|
||||
);
|
||||
}
|
||||
elsif ($req->{action} eq 'invite_email'){
|
||||
|
@ -2022,18 +2041,6 @@ get '/:room' => sub {
|
|||
}
|
||||
# Create a session if not already done
|
||||
$self->login;
|
||||
# If the room is locked and we're not the owner, we cannot join it !
|
||||
if ($data->{'locked'} &&
|
||||
(!$self->session($room) ||
|
||||
!$self->session($room)->{role} ||
|
||||
$self->session($room)->{role} ne 'owner')){
|
||||
return $self->render('error',
|
||||
msg => sprintf($self->l("ERROR_ROOM_s_LOCKED"), $room),
|
||||
err => 'ERROR_ROOM_s_LOCKED',
|
||||
room => $room,
|
||||
ownerPass => ($data->{owner_password}) ? '1':'0'
|
||||
);
|
||||
}
|
||||
# If we've reached the members' limit
|
||||
my $limit = $self->get_member_limit($room);
|
||||
if ($limit > 0 && scalar $self->get_room_members($room) >= $limit){
|
||||
|
|
Loading…
Reference in New Issue