XMPP authentication improvements. Makes it possible to authenticate during the conference.
This commit is contained in:
parent
7c201573fb
commit
588c2d9e4b
|
@ -132,6 +132,7 @@
|
|||
"passwordError2": "This conversation isn't currently protected by a password. Only the owner of the conference could set a password.",
|
||||
"joinError": "Oops! We couldn't join the conference. There might be some problem with security configuration. Please contact service administrator.",
|
||||
"connectError": "Oops! Something went wrong and we couldn't connect to the conference.",
|
||||
"connecting": "Connecting",
|
||||
"error": "Error",
|
||||
"detectext": "Error when trying to detect desktopsharing extension.",
|
||||
"failtoinstall": "Failed to install desktop sharing extension",
|
||||
|
@ -159,6 +160,7 @@
|
|||
"AuthMsg": "Authentication is required to create room:<br/><b>__room__ </b></br> You can either authenticate to create the room or just wait for someone else to do so.",
|
||||
"Authenticate": "Authenticate",
|
||||
"Cancel": "Cancel",
|
||||
"retry": "Retry",
|
||||
"logoutTitle" : "Logout",
|
||||
"logoutQuestion" : "Are you sure you want to logout and stop the conference?",
|
||||
"sessTerminated": "Session Terminated",
|
||||
|
@ -216,5 +218,20 @@
|
|||
"Talk to you in a sec!"
|
||||
],
|
||||
"and": "and"
|
||||
},
|
||||
"connection":
|
||||
{
|
||||
"ERROR": "Error",
|
||||
"CONNECTING": "Connecting",
|
||||
"CONNFAIL": "Connection failed",
|
||||
"AUTHENTICATING": "Authenticating",
|
||||
"AUTHFAIL": "Authentication failed",
|
||||
"CONNECTED": "Connected",
|
||||
"DISCONNECTED": "Disconnected",
|
||||
"DISCONNECTING": "Disconnecting",
|
||||
"ATTACHED": "Attached",
|
||||
"FETCH_SESSION_ID": "Obtaining session-id...",
|
||||
"GOT_SESSION_ID": "Obtaining session-id... Done",
|
||||
"GET_SESSION_ID_ERROR": "Get session-id error: "
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
/* global $, APP */
|
||||
/* global $, APP*/
|
||||
|
||||
var LoginDialog = require('./LoginDialog');
|
||||
var Moderator = require('../../xmpp/moderator');
|
||||
|
||||
/* Initial "authentication required" dialog */
|
||||
var authDialog = null;
|
||||
|
@ -50,6 +53,37 @@ var Authentication = {
|
|||
authenticationWindow = null;
|
||||
}
|
||||
},
|
||||
xmppAuthenticate: function () {
|
||||
|
||||
var loginDialog = LoginDialog.show(
|
||||
function (connection, state) {
|
||||
if (!state) {
|
||||
// User cancelled
|
||||
loginDialog.close();
|
||||
return;
|
||||
} else if (state == APP.xmpp.Status.CONNECTED) {
|
||||
|
||||
loginDialog.close();
|
||||
|
||||
Authentication.stopInterval();
|
||||
Authentication.closeAuthenticationDialog();
|
||||
|
||||
// Close the connection as anonymous one will be used
|
||||
// to create the conference. Session-id will authorize
|
||||
// the request.
|
||||
connection.disconnect();
|
||||
|
||||
var roomName = APP.UI.generateRoomName();
|
||||
Moderator.allocateConferenceFocus(roomName, function () {
|
||||
// If it's not "on the fly" authentication now join
|
||||
// the conference room
|
||||
if (!APP.xmpp.getMUCJoined()) {
|
||||
APP.UI.checkForNicknameAndJoin();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, true);
|
||||
},
|
||||
focusAuthenticationWindow: function () {
|
||||
// If auth window exists just bring it to the front
|
||||
if (authenticationWindow) {
|
||||
|
@ -60,7 +94,7 @@ var Authentication = {
|
|||
closeAuthenticationDialog: function () {
|
||||
// Close authentication dialog if opened
|
||||
if (authDialog) {
|
||||
APP.UI.messageHandler.closeDialog();
|
||||
authDialog.close();
|
||||
authDialog = null;
|
||||
}
|
||||
},
|
||||
|
@ -70,10 +104,7 @@ var Authentication = {
|
|||
// On closed
|
||||
function () {
|
||||
// Close authentication dialog if opened
|
||||
if (authDialog) {
|
||||
messageHandler.closeDialog();
|
||||
authDialog = null;
|
||||
}
|
||||
Authentication.closeAuthenticationDialog();
|
||||
callback();
|
||||
authenticationWindow = null;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
/* global $, APP, config*/
|
||||
|
||||
var XMPP = require('../../xmpp/xmpp');
|
||||
var Moderator = require('../../xmpp/moderator');
|
||||
|
||||
//FIXME: use LoginDialog to add retries to XMPP.connect method used when
|
||||
// anonymous domain is not enabled
|
||||
|
||||
/**
|
||||
* Creates new <tt>Dialog</tt> instance.
|
||||
* @param callback <tt>function(Strophe.Connection, Strophe.Status)</tt> called
|
||||
* when we either fail to connect or succeed(check Strophe.Status).
|
||||
* @param obtainSession <tt>true</tt> if we want to send ConferenceIQ to Jicofo
|
||||
* in order to create session-id after the connection is established.
|
||||
* @constructor
|
||||
*/
|
||||
function Dialog(callback, obtainSession) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var stop = false;
|
||||
|
||||
var connection = APP.xmpp.createConnection();
|
||||
|
||||
var message = '<h2 data-i18n="dialog.passwordRequired">';
|
||||
message += APP.translation.translateString("dialog.passwordRequired");
|
||||
message += '</h2>' +
|
||||
'<input name="username" type="text" ' +
|
||||
'placeholder="user@domain.net" autofocus>' +
|
||||
'<input name="password" ' +
|
||||
'type="password" data-i18n="[placeholder]dialog.userPassword"' +
|
||||
' placeholder="user password">';
|
||||
|
||||
var okButton = APP.translation.generateTranslatonHTML("dialog.Ok");
|
||||
|
||||
var cancelButton = APP.translation.generateTranslatonHTML("dialog.Cancel");
|
||||
|
||||
var states = {
|
||||
login: {
|
||||
html: message,
|
||||
buttons: [
|
||||
{ title: okButton, value: true},
|
||||
{ title: cancelButton, value: false}
|
||||
],
|
||||
focus: ':input:first',
|
||||
submit: function (e, v, m, f) {
|
||||
e.preventDefault();
|
||||
if (v) {
|
||||
var jid = f.username;
|
||||
var password = f.password;
|
||||
if (jid && password) {
|
||||
stop = false;
|
||||
connection.reset();
|
||||
connDialog.goToState('connecting');
|
||||
connection.connect(jid, password, stateHandler);
|
||||
}
|
||||
} else {
|
||||
// User cancelled
|
||||
stop = true;
|
||||
callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
connecting: {
|
||||
title: APP.translation.translateString('dialog.connecting'),
|
||||
html: '<div id="connectionStatus"></div>',
|
||||
buttons: [],
|
||||
defaultButton: 0
|
||||
},
|
||||
finished: {
|
||||
title: APP.translation.translateString('dialog.error'),
|
||||
html: '<div id="errorMessage"></div>',
|
||||
buttons: [
|
||||
{
|
||||
title: APP.translation.translateString('dialog.retry'),
|
||||
value: 'retry'
|
||||
},
|
||||
{
|
||||
title: APP.translation.translateString('dialog.Cancel'),
|
||||
value: 'cancel'
|
||||
},
|
||||
],
|
||||
defaultButton: 0,
|
||||
submit: function (e, v, m, f) {
|
||||
e.preventDefault();
|
||||
if (v === 'retry')
|
||||
connDialog.goToState('login');
|
||||
else
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var connDialog
|
||||
= APP.UI.messageHandler.openDialogWithStates(states,
|
||||
{ persistent: true, closeText: '' }, null);
|
||||
|
||||
var stateHandler = function (status, message) {
|
||||
if (stop) {
|
||||
return;
|
||||
}
|
||||
|
||||
var translateKey = "connection." + XMPP.getStatusString(status);
|
||||
var statusStr = APP.translation.translateString(translateKey);
|
||||
|
||||
// Display current state
|
||||
var connectionStatus =
|
||||
connDialog.getState('connecting').find('#connectionStatus');
|
||||
|
||||
connectionStatus.text(statusStr);
|
||||
|
||||
switch (status) {
|
||||
case XMPP.Status.CONNECTED:
|
||||
|
||||
stop = true;
|
||||
if (!obtainSession) {
|
||||
callback(connection, status);
|
||||
return;
|
||||
}
|
||||
// Obtaining session-id status
|
||||
connectionStatus.text(
|
||||
APP.translation.translateString(
|
||||
'connection.FETCH_SESSION_ID'));
|
||||
|
||||
// Authenticate with Jicofo and obtain session-id
|
||||
var roomName = APP.UI.generateRoomName();
|
||||
|
||||
// Jicofo will return new session-id when connected
|
||||
// from authenticated domain
|
||||
connection.sendIQ(
|
||||
Moderator.createConferenceIq(roomName),
|
||||
function (result) {
|
||||
|
||||
connectionStatus.text(
|
||||
APP.translation.translateString(
|
||||
'connection.GOT_SESSION_ID'));
|
||||
|
||||
stop = true;
|
||||
|
||||
// Parse session-id
|
||||
Moderator.parseSessionId(result);
|
||||
|
||||
callback(connection, status);
|
||||
},
|
||||
function (error) {
|
||||
console.error("Auth on the fly failed", error);
|
||||
|
||||
stop = true;
|
||||
|
||||
var errorMsg =
|
||||
APP.translation.translateString(
|
||||
'connection.GET_SESSION_ID_ERROR') +
|
||||
$(error).find('>error').attr('code');
|
||||
|
||||
self.displayError(errorMsg);
|
||||
|
||||
connection.disconnect();
|
||||
});
|
||||
|
||||
break;
|
||||
case XMPP.Status.AUTHFAIL:
|
||||
case XMPP.Status.CONNFAIL:
|
||||
case XMPP.Status.DISCONNECTED:
|
||||
|
||||
stop = true;
|
||||
|
||||
callback(connection, status);
|
||||
|
||||
var errorMessage = statusStr;
|
||||
|
||||
if (message)
|
||||
{
|
||||
errorMessage += ': ' + message;
|
||||
}
|
||||
self.displayError(errorMessage);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays error message in 'finished' state which allows either to cancel
|
||||
* or retry.
|
||||
* @param message the final message to be displayed.
|
||||
*/
|
||||
this.displayError = function (message) {
|
||||
|
||||
var finishedState = connDialog.getState('finished');
|
||||
|
||||
var errorMessageElem = finishedState.find('#errorMessage');
|
||||
errorMessageElem.text(message);
|
||||
|
||||
connDialog.goToState('finished');
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes LoginDialog.
|
||||
*/
|
||||
this.close = function () {
|
||||
stop = true;
|
||||
connDialog.close();
|
||||
};
|
||||
}
|
||||
|
||||
var LoginDialog = {
|
||||
|
||||
/**
|
||||
* Displays login prompt used to establish new XMPP connection. Given
|
||||
* <tt>callback(Strophe.Connection, Strophe.Status)</tt> function will be
|
||||
* called when we connect successfully(status === CONNECTED) or when we fail
|
||||
* to do so. On connection failure program can call Dialog.close() method in
|
||||
* order to cancel or do nothing to let the user retry.
|
||||
* @param callback <tt>function(Strophe.Connection, Strophe.Status)</tt>
|
||||
* called when we either fail to connect or succeed(check
|
||||
* Strophe.Status).
|
||||
* @param obtainSession <tt>true</tt> if we want to send ConferenceIQ to
|
||||
* Jicofo in order to create session-id after the connection is
|
||||
* established.
|
||||
* @returns {Dialog}
|
||||
*/
|
||||
show: function (callback, obtainSession) {
|
||||
return new Dialog(callback, obtainSession);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = LoginDialog;
|
|
@ -264,12 +264,6 @@ var Toolbar = (function (my) {
|
|||
loggedIn = true;
|
||||
}
|
||||
|
||||
//FIXME: XMPP authentication need improvements for "live" login
|
||||
if (!APP.xmpp.isExternalAuthEnabled() && !loggedIn)
|
||||
{
|
||||
authenticationEnabled = false;
|
||||
}
|
||||
|
||||
Toolbar.showAuthenticateButton(authenticationEnabled);
|
||||
|
||||
if (authenticationEnabled) {
|
||||
|
@ -292,6 +286,10 @@ var Toolbar = (function (my) {
|
|||
|
||||
my.authenticateClicked = function () {
|
||||
Authentication.focusAuthenticationWindow();
|
||||
if (!APP.xmpp.isExternalAuthEnabled()) {
|
||||
Authentication.xmppAuthenticate();
|
||||
return;
|
||||
}
|
||||
// Get authentication URL
|
||||
if (!APP.xmpp.getMUCJoined()) {
|
||||
APP.xmpp.getLoginUrl(UI.getRoomName(), function (url) {
|
||||
|
|
|
@ -94,7 +94,7 @@ var messageHandler = (function(my) {
|
|||
if (persistent) {
|
||||
args.closeText = '';
|
||||
}
|
||||
return $.prompt(msgString, args);
|
||||
return new Impromptu(msgString, args);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -108,16 +108,10 @@ var messageHandler = (function(my) {
|
|||
* Shows a dialog with different states to the user.
|
||||
*
|
||||
* @param statesObject object containing all the states of the dialog
|
||||
* @param loadedFunction function to be called after the prompt is fully loaded
|
||||
* @param stateChangedFunction function to be called when the state of the dialog is changed
|
||||
*/
|
||||
my.openDialogWithStates = function(statesObject, loadedFunction, stateChangedFunction) {
|
||||
my.openDialogWithStates = function (statesObject, options) {
|
||||
|
||||
|
||||
var myPrompt = $.prompt(statesObject);
|
||||
|
||||
myPrompt.on('impromptu:loaded', loadedFunction);
|
||||
myPrompt.on('impromptu:statechanged', stateChangedFunction);
|
||||
return new Impromptu(statesObject, options);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -188,6 +188,14 @@ var Moderator = {
|
|||
return elem;
|
||||
},
|
||||
|
||||
parseSessionId: function (resultIq) {
|
||||
var sessionId = $(resultIq).find('conference').attr('session-id');
|
||||
if (sessionId) {
|
||||
console.info('Received sessionId: ' + sessionId);
|
||||
localStorage.setItem('sessionId', sessionId);
|
||||
}
|
||||
},
|
||||
|
||||
parseConfigOptions: function (resultIq) {
|
||||
|
||||
Moderator.setFocusUserJid(
|
||||
|
@ -209,12 +217,7 @@ var Moderator = {
|
|||
|
||||
if (!externalAuthEnabled) {
|
||||
// We expect to receive sessionId in 'internal' authentication mode
|
||||
var sessionId
|
||||
= $(resultIq).find('conference').attr('session-id');
|
||||
if (sessionId) {
|
||||
console.info('Received sessionId: ' + sessionId);
|
||||
localStorage.setItem('sessionId', sessionId);
|
||||
}
|
||||
Moderator.parseSessionId(resultIq);
|
||||
}
|
||||
|
||||
var authIdentity = $(resultIq).find('>conference').attr('identity');
|
||||
|
@ -295,22 +298,12 @@ var Moderator = {
|
|||
// Not authorized to create new room
|
||||
if ($(error).find('>error>not-authorized').length) {
|
||||
console.warn("Unauthorized to start the conference", error);
|
||||
var toDomain
|
||||
= Strophe.getDomainFromJid(error.getAttribute('to'));
|
||||
if (toDomain === config.hosts.anonymousdomain) {
|
||||
// we are connected with anonymous domain and
|
||||
// only non anonymous users can create rooms
|
||||
// we must authorize the user
|
||||
self.xmppService.promptLogin();
|
||||
} else {
|
||||
// External authentication mode
|
||||
eventEmitter.emit(
|
||||
XMPPEvents.AUTHENTICATION_REQUIRED,
|
||||
function () {
|
||||
Moderator.allocateConferenceFocus(
|
||||
roomName, callback);
|
||||
});
|
||||
}
|
||||
eventEmitter.emit(
|
||||
XMPPEvents.AUTHENTICATION_REQUIRED,
|
||||
function () {
|
||||
Moderator.allocateConferenceFocus(
|
||||
roomName, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var waitMs = getNextErrorTimeout();
|
||||
|
|
|
@ -13,8 +13,7 @@ var connection = null;
|
|||
var authenticatedUser = false;
|
||||
|
||||
function connect(jid, password) {
|
||||
var bosh = config.bosh || '/http-bind';
|
||||
connection = new Strophe.Connection(bosh);
|
||||
connection = XMPP.createConnection();
|
||||
Moderator.setConnection(connection);
|
||||
|
||||
if (connection.disco) {
|
||||
|
@ -127,6 +126,12 @@ function setupEvents() {
|
|||
|
||||
var XMPP = {
|
||||
sessionTerminated: false,
|
||||
|
||||
/**
|
||||
* XMPP connection status
|
||||
*/
|
||||
Status: Strophe.Status,
|
||||
|
||||
/**
|
||||
* Remembers if we were muted by the focus.
|
||||
* @type {boolean}
|
||||
|
@ -146,7 +151,16 @@ var XMPP = {
|
|||
var jid = configDomain || window.location.hostname;
|
||||
connect(jid, null);
|
||||
},
|
||||
createConnection: function () {
|
||||
var bosh = config.bosh || '/http-bind';
|
||||
|
||||
return new Strophe.Connection(bosh);
|
||||
},
|
||||
getStatusString: function (status) {
|
||||
return Strophe.getStatusString(status);
|
||||
},
|
||||
promptLogin: function () {
|
||||
// FIXME: re-use LoginDialog which supports retries
|
||||
APP.UI.showLoginPopup(connect);
|
||||
},
|
||||
joinRoom: function(roomName, useNicks, nick)
|
||||
|
|
Loading…
Reference in New Issue