Add a "promote to owner" button

Fix #58
master
Daniel Berteaud 11 years ago
parent 8cac51e88f
commit 12b7f32e14
  1. 9
      lib/Vroom/I18N/en.pm
  2. 10
      lib/Vroom/I18N/fr.pm
  3. 4
      public/css/vroom.css
  4. 55
      public/js/vroom.js
  5. 37
      public/vroom.pl
  6. 3
      templates/default/join.html.ep

@ -161,13 +161,16 @@ our %Lexicon = (
"HELP_ASK_FOR_NAME_BUTTON" => "This will enforce participants to set their name before joining the room.", "HELP_ASK_FOR_NAME_BUTTON" => "This will enforce participants to set their name before joining the room.",
"HELP_LOGOUT_BUTTON" => "This will end the call and disconnect you from the room", "HELP_LOGOUT_BUTTON" => "This will end the call and disconnect you from the room",
"HELP_PEER_ACTIONS_BUTTONS" => "This menu will appear when you put the mouse over a video preview. It'll allow " . "HELP_PEER_ACTIONS_BUTTONS" => "This menu will appear when you put the mouse over a video preview. It'll allow " .
"you to run actions which only affect this peer (mute/suspend/kick from the room)", "you to run actions which only affect this peer (mute/suspend/grant admin rights/kick " .
"from the room). Warning: grating admin rights to someone is irrevocable, and he will " .
"be able to change configuration parameters (including passwords).",
"LOGOUT" => "Leave the room", "LOGOUT" => "Leave the room",
"SET_YOUR_NAME_TO_CHAT" => "You need to set your name to be able to chat", "SET_YOUR_NAME_TO_CHAT" => "You need to set your name to be able to chat",
"SEND_MESSAGE" => "Send the message", "SEND_MESSAGE" => "Send the message",
"SAVE_HISTORY" => "Save history to a file", "SAVE_HISTORY" => "Save history to a file",
"MUTE_PEER" => "Mute or unmute this participant's microphone", "MUTE_PEER" => "Mute or unmute this participant's microphone",
"SUSPEND_PEER" => "Suspend or resume this participant's webcam", "SUSPEND_PEER" => "Suspend or resume this participant's webcam",
"PROMOTE_PEER" => "Grant this participant administration privileges on the room",
"KICK_PEER" => "Kick this participant out of the room", "KICK_PEER" => "Kick this participant out of the room",
"s_IS_MUTING_YOU" => "%s has muted your microphone", "s_IS_MUTING_YOU" => "%s has muted your microphone",
"s_IS_MUTING_s" => "%s has muted %s's microphone", "s_IS_MUTING_s" => "%s has muted %s's microphone",
@ -177,6 +180,9 @@ our %Lexicon = (
"s_IS_SUSPENDING_s" => "%s has suspended %s's webcam", "s_IS_SUSPENDING_s" => "%s has suspended %s's webcam",
"s_IS_RESUMING_YOU" => "%s has resumed your webcam", "s_IS_RESUMING_YOU" => "%s has resumed your webcam",
"s_IS_RESUMING_s" => "%s has resumed %s's webcam", "s_IS_RESUMING_s" => "%s has resumed %s's webcam",
"s_IS_PROMOTING_YOU" => "%s has granted you administration privileges on the room",
"s_IS_PROMOTING_s" => "%s has granted %s administration privileges on the room",
"PEER_PROMOTED" => "You have granted administration privileges on the room",
"s_IS_KICKING_s" => "%s has kicked %s out of the room", "s_IS_KICKING_s" => "%s has kicked %s out of the room",
"KICKED" => "Kicked", "KICKED" => "Kicked",
"YOU_HAVE_BEEN_KICKED" => "You've been kicked out of the room", "YOU_HAVE_BEEN_KICKED" => "You've been kicked out of the room",
@ -189,6 +195,7 @@ our %Lexicon = (
"CANT_SUSPEND_OWNER" => "You can't suspend this participant's webcam", "CANT_SUSPEND_OWNER" => "You can't suspend this participant's webcam",
"YOU_HAVE_KICKED_s" => "You have kicked %s out of the room", "YOU_HAVE_KICKED_s" => "You have kicked %s out of the room",
"CANT_KICK_OWNER" => "You can't kick this participant out of the room", "CANT_KICK_OWNER" => "You can't kick this participant out of the room",
"CANT_PROMOTE_OWNER" => "This participant already has administration privileges on the room",
"A_ROOM_ADMIN" => "a room administrator", "A_ROOM_ADMIN" => "a room administrator",
"A_PARTICIPANT" => "a participant", "A_PARTICIPANT" => "a participant",
"MIC_MUTED" => "Your microphone is now muted", "MIC_MUTED" => "Your microphone is now muted",

@ -181,13 +181,17 @@ our %Lexicon = (
"HELP_LOGOUT_BUTTON" => "Ce bouton vous déconnectera du système", "HELP_LOGOUT_BUTTON" => "Ce bouton vous déconnectera du système",
"HELP_PEER_ACTIONS_BUTTONS" => "Ce menu s'affiche en passant la souris au dessus d'une vignette vidéo. Il " . "HELP_PEER_ACTIONS_BUTTONS" => "Ce menu s'affiche en passant la souris au dessus d'une vignette vidéo. Il " .
"vous permet d'effectuer certaines actions qui ne concerneront que cette " . "vous permet d'effectuer certaines actions qui ne concerneront que cette " .
"personne (coupé le micro, mettre la webcam en pause, et bannir du salon)", "personne (coupé le micro, mettre la webcam en pause, donner les droits " .
"d'administration sur le salon et bannir du salon). Attention: donner les droits " .
"d'administration à quelqu'un est irrévocable, et il pourra modifier tous les " .
"paramètres (y compris les mots de passe).",
"LOGOUT" => "Quitter le salon", "LOGOUT" => "Quitter le salon",
"SET_YOUR_NAME_TO_CHAT" => "Vous devez saisir votre nom avant de pouvoir tchater", "SET_YOUR_NAME_TO_CHAT" => "Vous devez saisir votre nom avant de pouvoir tchater",
"SEND_MESSAGE" => "Envoyer le message", "SEND_MESSAGE" => "Envoyer le message",
"SAVE_HISTORY" => "Sauvegarder l'historique dans un fichier", "SAVE_HISTORY" => "Sauvegarder l'historique dans un fichier",
"MUTE_PEER" => "Couper ou réactiver le micro de ce participant", "MUTE_PEER" => "Couper ou réactiver le micro de ce participant",
"SUSPEND_PEER" => "Mettre en pause ou réactiver la webcam de ce participant", "SUSPEND_PEER" => "Mettre en pause ou réactiver la webcam de ce participant",
"PROMOTE_PEER" => "Donner les droits d'administration du salon à ce participant",
"KICK_PEER" => "Éjecter ce participant du salon", "KICK_PEER" => "Éjecter ce participant du salon",
"s_IS_MUTING_YOU" => "%s a coupé votre micro", "s_IS_MUTING_YOU" => "%s a coupé votre micro",
"s_IS_MUTING_s" => "%s a coupé le micro de %s", "s_IS_MUTING_s" => "%s a coupé le micro de %s",
@ -197,6 +201,9 @@ our %Lexicon = (
"s_IS_SUSPENDING_s" => "%s a mis la webcam de %s en pause", "s_IS_SUSPENDING_s" => "%s a mis la webcam de %s en pause",
"s_IS_RESUMING_YOU" => "%s a réactivé votre webcam", "s_IS_RESUMING_YOU" => "%s a réactivé votre webcam",
"s_IS_RESUMING_s" => "%s a réactivé la webcam de %s", "s_IS_RESUMING_s" => "%s a réactivé la webcam de %s",
"s_IS_PROMOTING_YOU" => "%s vous a donné les droits d'administration du salon",
"s_IS_PROMOTING_s" => "%s a donné les droits d'administration du salon à %s",
"PEER_PROMOTED" => "Vous avez donné les droits sur ce salon",
"s_IS_KICKING_s" => "%s a éjecté %s du salon", "s_IS_KICKING_s" => "%s a éjecté %s du salon",
"KICKED" => "Éjecté", "KICKED" => "Éjecté",
"YOU_HAVE_BEEN_KICKED" => "Vous avez été banni du salon", "YOU_HAVE_BEEN_KICKED" => "Vous avez été banni du salon",
@ -209,6 +216,7 @@ our %Lexicon = (
"CANT_SUSPEND_OWNER" => "Vous ne pouvez pas mettre la webcam de ce participant en pause", "CANT_SUSPEND_OWNER" => "Vous ne pouvez pas mettre la webcam de ce participant en pause",
"YOU_HAVE_KICKED_s" => "Vous avez bani %s du salon", "YOU_HAVE_KICKED_s" => "Vous avez bani %s du salon",
"CANT_KICK_OWNER" => "Vous ne pouvez pas bannir ce participant", "CANT_KICK_OWNER" => "Vous ne pouvez pas bannir ce participant",
"CANT_PROMOTE_OWNER" => "Ce participant dispose déjà des droits d'administration",
"A_ROOM_ADMIN" => "un administrateur du salon", "A_ROOM_ADMIN" => "un administrateur du salon",
"A_PARTICIPANT" => "un participant", "A_PARTICIPANT" => "un participant",
"MIC_MUTED" => "Votre micro est coupé", "MIC_MUTED" => "Votre micro est coupé",

@ -125,6 +125,10 @@
font-family: 'Glyphicons Halflings'; font-family: 'Glyphicons Halflings';
content: "\e106"; content: "\e106";
} }
.actionPromote:before{
font-family: 'Glyphicons Halflings';
content: "\e124";
}
.actionKick:before{ .actionKick:before{
font-family: 'Glyphicons Halflings'; font-family: 'Glyphicons Halflings';
content: "\e083"; content: "\e083";

@ -51,9 +51,12 @@ var locale = {
s_IS_SUSPENDING_s: '', s_IS_SUSPENDING_s: '',
s_IS_RESUMING_YOU: '', s_IS_RESUMING_YOU: '',
s_IS_RESUMING_s: '', s_IS_RESUMING_s: '',
s_IS_PROMOTING_YOU: '',
s_IS_PROMOTING_s: '',
s_IS_KICKING_s: '', s_IS_KICKING_s: '',
MUTE_PEER: '', MUTE_PEER: '',
SUSPEND_PEER: '', SUSPEND_PEER: '',
PROMOTE_PEER: '',
KICK_PEER: '', KICK_PEER: '',
YOU_HAVE_MUTED_s: '', YOU_HAVE_MUTED_s: '',
YOU_HAVE_UNMUTED_s: '', YOU_HAVE_UNMUTED_s: '',
@ -61,6 +64,7 @@ var locale = {
YOU_HAVE_SUSPENDED_s: '', YOU_HAVE_SUSPENDED_s: '',
YOU_HAVE_RESUMED_s: '', YOU_HAVE_RESUMED_s: '',
CANT_SUSPEND_OWNER: '', CANT_SUSPEND_OWNER: '',
CANT_PROMOTE_OWNER: '',
YOU_HAVE_KICKED_s: '', YOU_HAVE_KICKED_s: '',
CANT_KICK_OWNER: '', CANT_KICK_OWNER: '',
REMOVE_THIS_ADDRESS: '', REMOVE_THIS_ADDRESS: '',
@ -539,6 +543,11 @@ function initVroom(room) {
click: function() { pausePeer(id) }, click: function() { pausePeer(id) },
}).prop('title', locale.SUSPEND_PEER)) }).prop('title', locale.SUSPEND_PEER))
.append($('<button></button>', { .append($('<button></button>', {
class: 'actionPromote btn btn-default btn-sm',
id: 'actionPromote_' + id,
click: function() { promotePeer(id) },
}).prop('title', locale.PROMOTE_PEER))
.append($('<button></button>', {
class: 'actionKick btn btn-default btn-sm', class: 'actionKick btn btn-default btn-sm',
id: 'actionKick_' + id, id: 'actionKick_' + id,
click: function() { kickPeer(id) }, click: function() { kickPeer(id) },
@ -723,6 +732,34 @@ function initVroom(room) {
$.notify(locale.CANT_SUSPEND_OWNER, 'error'); $.notify(locale.CANT_SUSPEND_OWNER, 'error');
} }
} }
// Promote a peer (he will be owner)
function promotePeer(id){
if (peers[id] && peers[id].role != 'owner'){
$.ajax({
data: {
action: 'promote',
room: roomName,
peer: id
},
error: function(data) {
$.notify(locale.ERROR_OCCURRED, 'error');
},
success: function(data) {
if (data.status == 'success' && data.msg){
webrtc.sendToAll('owner_promoted', {peer: id});
$.notify(data.msg, 'success');
}
else if (data.msg){
$.notify(data.msg, 'error');
}
}
});
suspendButton($('#actionPromote_' + id));
}
else if (peers[id]){
$.notify(locale.CANT_PROMOTE_OWNER, 'error');
}
}
// Kick a peer // Kick a peer
function kickPeer(id){ function kickPeer(id){
if (peers[id] && peers[id].role != 'owner'){ if (peers[id] && peers[id].role != 'owner'){
@ -848,6 +885,24 @@ function initVroom(room) {
} }
} }
}); });
// An owner has just promoted a participant of the room to the owner role
webrtc.on('owner_promoted', function(data){
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){
return;
}
if (data.payload.peer && data.payload.peer == peers.local.id && peers.local.role != 'owner'){
var who = (peers[data.id].hasName) ? peers[data.id].displayName : locale.A_ROOM_ADMIN;
$.notify(sprintf(locale.s_IS_PROMOTING_YOU, who), 'success');
getRoomInfo();
}
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){
var who = (peers[data.id].hasName) ? peers[data.id].displayName : locale.A_ROOM_ADMIN;
var target = (peers[data.payload.peer].hasName) ? peers[data.payload.peer].displayName : locale.A_PARTICIPANT;
$.notify(sprintf(locale.s_IS_PROMOTING_s, who, target), 'info');
}
});
// An owner is kicking someone out of the room // An owner is kicking someone out of the room
webrtc.on('owner_kick', function(data){ webrtc.on('owner_kick', function(data){
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ if (peers[data.id].role != 'owner' || data.roomType == 'screen'){

@ -279,6 +279,18 @@ helper get_peer_role => sub {
} }
}; };
# Promote a peer to owner
helper promote_peer => sub {
my $self = shift;
my ($room,$id) = @_;
my $sth = eval { $self->db->prepare("SELECT * FROM `participants` WHERE `peer_id`=? AND `id` IN (SELECT `id` FROM `rooms` WHERE `name`=?)") } || return undef;
$sth->execute($id,$room) || return undef;
return undef if ($sth->rows != 1);
$sth = eval { $self->db->prepare("UPDATE `participants` SET `role`='owner' WHERE `peer_id`=? AND `id` IN (SELECT `id` FROM `rooms` WHERE `name`=?)") } || return undef;
$sth->execute($id,$room) || return undef;
return 1;
};
# Check if a participant has joined a room # Check if a participant has joined a room
# Takes two args: the session name, and the room name # Takes two args: the session name, and the room name
helper has_joined => sub { helper has_joined => sub {
@ -1013,6 +1025,9 @@ post '/action' => sub {
my $res = 'error'; my $res = 'error';
my %emailNotif; my %emailNotif;
if ($self->session($room) && $self->session($room)->{role}){ if ($self->session($room) && $self->session($room)->{role}){
if ($self->session($room)->{role} ne 'owner' && $self->get_peer_role($room,$id) eq 'owner'){
$self->session($room)->{role} = 'owner';
}
$res = ($self->set_peer_role($room,$self->session('name'),$id, $self->session($room)->{role})) ? 'success':$res; $res = ($self->set_peer_role($room,$self->session('name'),$id, $self->session($room)->{role})) ? 'success':$res;
} }
if ($self->session($room)->{role} eq 'owner'){ if ($self->session($room)->{role} eq 'owner'){
@ -1117,6 +1132,28 @@ post '/action' => sub {
} }
); );
} }
# A participant is being promoted to the owner status
elsif ($action eq 'promote'){
my $peer = $self->param('peer');
my $status = 'error';
my $msg = $self->l('ERROR_OCCURRED');
if (!$peer){
$msg = $self->l('ERROR_OCCURRED');
}
elsif ($self->session($room)->{role} ne 'owner'){
$msg = $self->l('NOT_ALLOWED');
}
elsif ($self->promote_peer($room,$peer)){
$status = 'success';
$msg = $self->l('PEER_PROMOTED');
}
return $self->render(
json => {
msg => $msg,
status => $status
}
);
}
}; };
# use the templates defined in the config # use the templates defined in the config

@ -495,6 +495,9 @@
<span class="glyphicon glyphicon-eye-close"></span> <span class="glyphicon glyphicon-eye-close"></span>
</div> </div>
<div class="btn btn-sm btn-default"> <div class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-certificate"></span>
</div>
<div class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> <span class="glyphicon glyphicon-remove-circle"></span>
</div> </div>
</center> </center>

Loading…
Cancel
Save