Adds functionality for authentication with external system.
This commit is contained in:
parent
cc38c2641b
commit
f4004656a3
92
app.js
92
app.js
|
@ -2,11 +2,12 @@
|
|||
/* application specific logic */
|
||||
var connection = null;
|
||||
var authenticatedUser = false;
|
||||
var authenticationWindow = null;
|
||||
var activecall = null;
|
||||
var RTC = null;
|
||||
var nickname = null;
|
||||
var sharedKey = '';
|
||||
var focusJid = null;
|
||||
var focusMucJid = null;
|
||||
var roomUrl = null;
|
||||
var roomName = null;
|
||||
var ssrc2jid = {};
|
||||
|
@ -164,6 +165,8 @@ function connect(jid, password) {
|
|||
}
|
||||
document.getElementById('connect').disabled = true;
|
||||
|
||||
console.info("My Jabber ID: " + connection.jid);
|
||||
|
||||
if(password)
|
||||
authenticatedUser = true;
|
||||
maybeDoJoin();
|
||||
|
@ -755,6 +758,10 @@ $(document).bind('joined.muc', function (event, jid, info) {
|
|||
// Once we've joined the muc show the toolbar
|
||||
ToolbarToggler.showToolbar();
|
||||
|
||||
// Show authenticate button if needed
|
||||
Toolbar.showAuthenticateButton(
|
||||
Moderator.isExternalAuthEnabled() && !Moderator.isModerator());
|
||||
|
||||
var displayName = !config.displayJids
|
||||
? info.displayName : Strophe.getResourceFromJid(jid);
|
||||
|
||||
|
@ -767,10 +774,8 @@ $(document).bind('entered.muc', function (event, jid, info, pres) {
|
|||
console.log('entered', jid, info);
|
||||
if (info.isFocus)
|
||||
{
|
||||
focusJid = jid;
|
||||
focusMucJid = jid;
|
||||
console.info("Ignore focus: " + jid +", real JID: " + info.jid);
|
||||
// We don't want this notification for the focus.
|
||||
// messageHandler.notify('Focus', 'connected', 'connected');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -944,6 +949,44 @@ $(document).bind('kicked.muc', function (event, jid) {
|
|||
}
|
||||
});
|
||||
|
||||
$(document).bind('role.changed.muc', function (event, jid, member, pres) {
|
||||
console.info("Role changed for " + jid + ", new role: " + member.role);
|
||||
|
||||
VideoLayout.showModeratorIndicator();
|
||||
|
||||
if (member.role === 'moderator') {
|
||||
var displayName = member.displayName;
|
||||
if (!displayName) {
|
||||
displayName = 'Somebody';
|
||||
}
|
||||
messageHandler.notify(
|
||||
displayName,
|
||||
'connected',
|
||||
'Moderator rights granted to ' + displayName + '!');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$(document).bind('local.role.changed.muc', function (event, jid, info, pres) {
|
||||
|
||||
console.info("My role changed, new role: " + info.role);
|
||||
var isModerator = Moderator.isModerator();
|
||||
|
||||
VideoLayout.showModeratorIndicator();
|
||||
Toolbar.showAuthenticateButton(
|
||||
Moderator.isExternalAuthEnabled() && !isModerator);
|
||||
|
||||
if (isModerator) {
|
||||
if (authenticationWindow) {
|
||||
authenticationWindow.close();
|
||||
authenticationWindow = null;
|
||||
}
|
||||
messageHandler.notify(
|
||||
'Me', 'connected', 'Moderator rights granted !');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$(document).bind('passwordrequired.muc', function (event, jid) {
|
||||
console.log('on password required', jid);
|
||||
|
||||
|
@ -996,6 +1039,44 @@ $(document).bind('passwordrequired.main', function (event) {
|
|||
);
|
||||
});
|
||||
|
||||
$(document).bind('auth_required.moderator', function () {
|
||||
// extract room name from 'room@muc.server.net'
|
||||
var room = roomName.substr(0, roomName.indexOf('@'));
|
||||
|
||||
messageHandler.openDialog(
|
||||
'Stop',
|
||||
'Authentication is required to create room:<br/>' + room,
|
||||
true,
|
||||
{
|
||||
Authenticate: 'authNow',
|
||||
Close: 'close'
|
||||
},
|
||||
function (onSubmitEvent, submitValue) {
|
||||
console.info('On submit: ' + submitValue, submitValue);
|
||||
if (submitValue === 'authNow') {
|
||||
authenticateClicked();
|
||||
} else {
|
||||
Toolbar.showAuthenticateButton(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
function authenticateClicked() {
|
||||
// Get authentication URL
|
||||
Moderator.getAuthUrl(function (url) {
|
||||
// Open popup with authentication URL
|
||||
authenticationWindow = messageHandler.openCenteredPopup(
|
||||
url, 500, 400,
|
||||
function () {
|
||||
// On popup closed - retry room allocation
|
||||
Moderator.allocateConferenceFocus(
|
||||
roomName, doJoinAfterFocus);
|
||||
authenticationWindow = null;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if video identified by given src is desktop stream.
|
||||
* @param videoSrc eg.
|
||||
|
@ -1474,6 +1555,9 @@ $(window).bind('beforeunload', function () {
|
|||
});
|
||||
|
||||
function disposeConference(onUnload) {
|
||||
|
||||
Toolbar.showAuthenticateButton(false);
|
||||
|
||||
var handler = getConferenceHandler();
|
||||
if (handler && handler.peerconnection) {
|
||||
// FIXME: probably removing streams is not required and close() should
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
.icon-recEnable:before {
|
||||
content: "\e614";
|
||||
}
|
||||
.icon-authenticate:before {
|
||||
content: "\e1ae";
|
||||
}
|
||||
.icon-kick1:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
|
|
@ -184,6 +184,12 @@
|
|||
<a class="button" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" content="Start / stop camera" onclick='toggleVideo();'>
|
||||
<i id="video" class="icon-camera"></i>
|
||||
</a>
|
||||
<span id="authentication" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Authenticate" onclick='authenticateClicked();'>
|
||||
<i id="authButton" class="icon-avatar"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="recording" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Record" onclick='toggleRecording();'>
|
||||
|
|
|
@ -80,6 +80,32 @@ var messageHandler = (function(my) {
|
|||
myPrompt.on('impromptu:statechanged', stateChangedFunction);
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens new popup window for given <tt>url</tt> centered over current
|
||||
* window.
|
||||
*
|
||||
* @param url the URL to be displayed in the popup window
|
||||
* @param w the width of the popup window
|
||||
* @param h the height of the popup window
|
||||
* @param onPopupClosed optional callback function called when popup window
|
||||
* has been closed.
|
||||
*/
|
||||
my.openCenteredPopup = function (url, w, h, onPopupClosed) {
|
||||
var l = window.screenX + (window.innerWidth / 2) - (w / 2);
|
||||
var t = window.screenY + (window.innerHeight / 2) - (h / 2);
|
||||
var popup = window.open(
|
||||
url, '_blank',
|
||||
'top=' + t + ', left=' + l + ', width=' + w + ', height=' + h + '');
|
||||
if (onPopupClosed) {
|
||||
var pollTimer = window.setInterval(function () {
|
||||
if (popup.closed !== false) {
|
||||
window.clearInterval(pollTimer);
|
||||
onPopupClosed();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a dialog prompting the user to send an error report.
|
||||
*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global $, $iq, config, connection, focusJid, forceMuted, messageHandler,
|
||||
/* global $, $iq, config, connection, focusMucJid, forceMuted, messageHandler,
|
||||
setAudioMuted, Strophe, toggleAudio */
|
||||
/**
|
||||
* Moderate connection plugin.
|
||||
|
@ -17,7 +17,7 @@ Strophe.addConnectionPlugin('moderate', {
|
|||
},
|
||||
setMute: function (jid, mute) {
|
||||
console.info("set mute", mute);
|
||||
var iqToFocus = $iq({to: focusJid, type: 'set'})
|
||||
var iqToFocus = $iq({to: focusMucJid, type: 'set'})
|
||||
.c('mute', {
|
||||
xmlns: 'http://jitsi.org/jitmeet/audio',
|
||||
jid: jid
|
||||
|
@ -40,7 +40,7 @@ Strophe.addConnectionPlugin('moderate', {
|
|||
},
|
||||
onMute: function (iq) {
|
||||
var from = iq.getAttribute('from');
|
||||
if (from !== focusJid) {
|
||||
if (from !== focusMucJid) {
|
||||
console.warn("Ignored mute from non focus peer");
|
||||
return false;
|
||||
}
|
||||
|
|
71
moderator.js
71
moderator.js
|
@ -9,11 +9,21 @@ var Moderator = (function (my) {
|
|||
var focusUserJid;
|
||||
var getNextTimeout = Util.createExpBackoffTimer(1000);
|
||||
var getNextErrorTimeout = Util.createExpBackoffTimer(1000);
|
||||
// External authentication stuff
|
||||
var externalAuthEnabled = false;
|
||||
|
||||
my.isModerator = function () {
|
||||
return connection.emuc.isModerator();
|
||||
};
|
||||
|
||||
my.isPeerModerator = function (peerJid) {
|
||||
return connection.emuc.getMemberRole(peerJid) === 'moderator';
|
||||
};
|
||||
|
||||
my.isExternalAuthEnabled = function () {
|
||||
return externalAuthEnabled;
|
||||
};
|
||||
|
||||
my.onModeratorStatusChanged = function (isModerator) {
|
||||
|
||||
Toolbar.showSipCallButton(isModerator);
|
||||
|
@ -27,25 +37,12 @@ var Moderator = (function (my) {
|
|||
if (isModerator && config.etherpad_base) {
|
||||
Etherpad.init();
|
||||
}
|
||||
|
||||
$(document).trigger('local.role.moderator', [isModerator]);
|
||||
};
|
||||
|
||||
my.init = function () {
|
||||
$(document).bind(
|
||||
'role.changed.muc',
|
||||
function (event, jid, info, pres) {
|
||||
console.info(
|
||||
"Role changed for " + jid + ", new role: " + info.role);
|
||||
VideoLayout.showModeratorIndicator();
|
||||
}
|
||||
);
|
||||
|
||||
$(document).bind(
|
||||
'local.role.changed.muc',
|
||||
function (event, jid, info, pres) {
|
||||
console.info("My role changed, new role: " + info.role);
|
||||
VideoLayout.showModeratorIndicator();
|
||||
Moderator.onModeratorStatusChanged(Moderator.isModerator());
|
||||
}
|
||||
);
|
||||
|
@ -141,6 +138,19 @@ var Moderator = (function (my) {
|
|||
return elem;
|
||||
};
|
||||
|
||||
my.parseConfigOptions = function (resultIq) {
|
||||
|
||||
Moderator.setFocusUserJid(
|
||||
$(resultIq).find('conference').attr('focusjid'));
|
||||
|
||||
var extAuthParam
|
||||
= $(resultIq).find('>conference>property[name=\'externalAuth\']');
|
||||
if (extAuthParam.length) {
|
||||
externalAuthEnabled = extAuthParam.attr('value') === 'true';
|
||||
}
|
||||
console.info("External authentication enabled: " + externalAuthEnabled);
|
||||
};
|
||||
|
||||
// FIXME: we need to show the fact that we're waiting for the focus
|
||||
// to the user(or that focus is not available)
|
||||
my.allocateConferenceFocus = function (roomName, callback) {
|
||||
|
@ -155,8 +165,9 @@ var Moderator = (function (my) {
|
|||
// Reset both timers
|
||||
getNextTimeout(true);
|
||||
getNextErrorTimeout(true);
|
||||
Moderator.setFocusUserJid(
|
||||
$(result).find('conference').attr('focusjid'));
|
||||
// Setup config options
|
||||
Moderator.parseConfigOptions(result);
|
||||
// Exec callback
|
||||
callback();
|
||||
} else {
|
||||
var waitMs = getNextTimeout();
|
||||
|
@ -171,6 +182,12 @@ var Moderator = (function (my) {
|
|||
}
|
||||
},
|
||||
function (error) {
|
||||
// Not authorized to create new room
|
||||
if ($(error).find('>error>not-authorized').length) {
|
||||
console.warn("Unauthorized to start the conference");
|
||||
$(document).trigger('auth_required.moderator');
|
||||
return;
|
||||
}
|
||||
var waitMs = getNextErrorTimeout();
|
||||
console.error("Focus error, retry after " + waitMs, error);
|
||||
// Show message
|
||||
|
@ -188,6 +205,30 @@ var Moderator = (function (my) {
|
|||
);
|
||||
};
|
||||
|
||||
my.getAuthUrl = function (urlCallback) {
|
||||
var iq = $iq({to: Moderator.getFocusComponent(), type: 'get'});
|
||||
iq.c('auth-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: roomName
|
||||
});
|
||||
connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var url = $(result).find('auth-url').attr('url');
|
||||
if (url) {
|
||||
console.info("Got auth url: " + url);
|
||||
urlCallback(url);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to get auth url fro mthe focus", result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
console.error("Get auth url error", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return my;
|
||||
}(Moderator || {}));
|
||||
|
||||
|
|
6
muc.js
6
muc.js
|
@ -503,5 +503,11 @@ Strophe.addConnectionPlugin('emuc', {
|
|||
},
|
||||
isModerator: function() {
|
||||
return this.role === 'moderator';
|
||||
},
|
||||
getMemberRole: function(peerJid) {
|
||||
if (this.members[peerJid]) {
|
||||
return this.members[peerJid].role;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global $, $iq, config, connection, focusJid, messageHandler, Moderator,
|
||||
/* global $, $iq, config, connection, focusMucJid, messageHandler, Moderator,
|
||||
Toolbar, Util */
|
||||
var Recording = (function (my) {
|
||||
var recordingToken = null;
|
||||
|
@ -13,7 +13,7 @@ var Recording = (function (my) {
|
|||
// with the new recording state, according to the IQ.
|
||||
my.setRecording = function (state, token, callback) {
|
||||
var self = this;
|
||||
var elem = $iq({to: focusJid, type: 'set'});
|
||||
var elem = $iq({to: focusMucJid, type: 'set'});
|
||||
elem.c('conference', {
|
||||
xmlns: 'http://jitsi.org/protocol/colibri'
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global ssrc2jid */
|
||||
/* global focusMucJid, ssrc2jid */
|
||||
/* jshint -W117 */
|
||||
/**
|
||||
* Calculates packet lost percent using the number of lost packets and the
|
||||
|
@ -324,7 +324,7 @@ StatsCollector.prototype.addStatsToBeLogged = function (reports) {
|
|||
};
|
||||
|
||||
StatsCollector.prototype.logStats = function () {
|
||||
if (!focusJid) {
|
||||
if (!focusMucJid) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,7 @@ StatsCollector.prototype.logStats = function () {
|
|||
content = Base64.encode(content);
|
||||
|
||||
// XEP-0337-ish
|
||||
var message = $msg({to: focusJid, type: 'normal'});
|
||||
var message = $msg({to: focusMucJid, type: 'normal'});
|
||||
message.c('log', { xmlns: 'urn:xmpp:eventlog',
|
||||
id: 'PeerConnectionStats'});
|
||||
message.c('message').t(content).up();
|
||||
|
|
13
toolbar.js
13
toolbar.js
|
@ -221,6 +221,19 @@ var Toolbar = (function (my) {
|
|||
buttonClick("#lockIcon", "icon-security icon-security-locked");
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows or hides authentication button
|
||||
* @param show <tt>true</tt> to show or <tt>false</tt> to hide
|
||||
*/
|
||||
my.showAuthenticateButton = function (show) {
|
||||
if (show) {
|
||||
$('#authentication').css({display: "inline"});
|
||||
}
|
||||
else {
|
||||
$('#authentication').css({display: "none"});
|
||||
}
|
||||
};
|
||||
|
||||
// Shows or hides the 'recording' button.
|
||||
my.showRecordingButton = function (show) {
|
||||
if (!config.enableRecording) {
|
||||
|
|
|
@ -485,7 +485,8 @@ var VideoLayout = (function (my) {
|
|||
if ($('#' + videoSpanId).length > 0) {
|
||||
// If there's been a focus change, make sure we add focus related
|
||||
// interface!!
|
||||
if (Moderator.isModerator() && $('#remote_popupmenu_' + resourceJid).length <= 0) {
|
||||
if (Moderator.isModerator() && !Moderator.isPeerModerator(peerJid)
|
||||
&& $('#remote_popupmenu_' + resourceJid).length <= 0) {
|
||||
addRemoteVideoMenu(peerJid,
|
||||
document.getElementById(videoSpanId));
|
||||
}
|
||||
|
@ -905,38 +906,42 @@ var VideoLayout = (function (my) {
|
|||
{
|
||||
createModeratorIndicatorElement(indicatorSpan[0]);
|
||||
}
|
||||
} else {
|
||||
Object.keys(connection.emuc.members).forEach(function (jid) {
|
||||
var member = connection.emuc.members[jid];
|
||||
if (member.role === 'moderator') {
|
||||
var moderatorId
|
||||
= 'participant_' + Strophe.getResourceFromJid(jid);
|
||||
|
||||
var moderatorContainer
|
||||
= document.getElementById(moderatorId);
|
||||
|
||||
if (Strophe.getResourceFromJid(jid) === 'focus') {
|
||||
// Skip server side focus
|
||||
return;
|
||||
}
|
||||
if (!moderatorContainer) {
|
||||
console.error("No moderator container for " + jid);
|
||||
return;
|
||||
}
|
||||
var indicatorSpan
|
||||
= $('#' + moderatorId + ' .focusindicator');
|
||||
|
||||
if (!indicatorSpan || indicatorSpan.length === 0) {
|
||||
indicatorSpan = document.createElement('span');
|
||||
indicatorSpan.className = 'focusindicator';
|
||||
|
||||
moderatorContainer.appendChild(indicatorSpan);
|
||||
|
||||
createModeratorIndicatorElement(indicatorSpan);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Object.keys(connection.emuc.members).forEach(function (jid) {
|
||||
var member = connection.emuc.members[jid];
|
||||
if (member.role === 'moderator') {
|
||||
var moderatorId
|
||||
= 'participant_' + Strophe.getResourceFromJid(jid);
|
||||
|
||||
var moderatorContainer
|
||||
= document.getElementById(moderatorId);
|
||||
|
||||
if (Strophe.getResourceFromJid(jid) === 'focus') {
|
||||
// Skip server side focus
|
||||
return;
|
||||
}
|
||||
if (!moderatorContainer) {
|
||||
console.error("No moderator container for " + jid);
|
||||
return;
|
||||
}
|
||||
var menuSpan = $('#' + moderatorId + '>span.remotevideomenu');
|
||||
if (menuSpan.length) {
|
||||
removeRemoteVideoMenu(moderatorId);
|
||||
}
|
||||
|
||||
var indicatorSpan
|
||||
= $('#' + moderatorId + ' .focusindicator');
|
||||
|
||||
if (!indicatorSpan || indicatorSpan.length === 0) {
|
||||
indicatorSpan = document.createElement('span');
|
||||
indicatorSpan.className = 'focusindicator';
|
||||
|
||||
moderatorContainer.appendChild(indicatorSpan);
|
||||
|
||||
createModeratorIndicatorElement(indicatorSpan);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1399,6 +1404,19 @@ var VideoLayout = (function (my) {
|
|||
popupmenuElement.appendChild(paddingSpan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes remote video menu element from video element identified by
|
||||
* given <tt>videoElementId</tt>.
|
||||
*
|
||||
* @param videoElementId the id of local or remote video element.
|
||||
*/
|
||||
function removeRemoteVideoMenu(videoElementId) {
|
||||
var menuSpan = $('#' + videoElementId + '>span.remotevideomenu');
|
||||
if (menuSpan.length) {
|
||||
menuSpan.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On contact list item clicked.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue