handle external auth; xmpp auth tbd
This commit is contained in:
parent
28e5bf4bec
commit
58d1c76ab0
152
app.js
152
app.js
|
@ -17,6 +17,11 @@ import URLProcessor from "./modules/config/URLProcessor";
|
|||
import RoomnameGenerator from './modules/util/RoomnameGenerator';
|
||||
import CQEvents from './service/connectionquality/CQEvents';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
import LoginDialog from './modules/UI/authentication/LoginDialog';
|
||||
import UIUtil from './modules/UI/util/UIUtil';
|
||||
|
||||
import {openConnection} from './modules/connection';
|
||||
import AuthHandler from './modules/AuthHandler';
|
||||
|
||||
import createRoomLocker from './modules/RoomLocker';
|
||||
|
||||
|
@ -42,7 +47,7 @@ function buildRoomName () {
|
|||
location ~ ^/([a-zA-Z0-9]+)$ {
|
||||
rewrite ^/(.*)$ / break;
|
||||
}
|
||||
*/
|
||||
*/
|
||||
if (path.length > 1) {
|
||||
roomName = path.substr(1).toLowerCase();
|
||||
} else {
|
||||
|
@ -104,62 +109,9 @@ const APP = {
|
|||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
function connect() {
|
||||
let connection = new JitsiMeetJS.JitsiConnection(null, null, {
|
||||
hosts: config.hosts,
|
||||
bosh: config.bosh,
|
||||
clientNode: config.clientNode
|
||||
});
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
let handlers = {};
|
||||
|
||||
function unsubscribe () {
|
||||
Object.keys(handlers).forEach(function (event) {
|
||||
connection.removeEventListener(event, handlers[event]);
|
||||
});
|
||||
}
|
||||
|
||||
handlers[ConnectionEvents.CONNECTION_ESTABLISHED] = function () {
|
||||
console.log('CONNECTED');
|
||||
unsubscribe();
|
||||
resolve(connection);
|
||||
};
|
||||
|
||||
function listenForFailure (event) {
|
||||
handlers[event] = function (...args) {
|
||||
console.error(`CONNECTION FAILED: ${event}`, ...args);
|
||||
|
||||
unsubscribe();
|
||||
reject([event, ...args]);
|
||||
};
|
||||
}
|
||||
|
||||
listenForFailure(ConnectionEvents.CONNECTION_FAILED);
|
||||
listenForFailure(ConnectionErrors.PASSWORD_REQUIRED);
|
||||
listenForFailure(ConnectionErrors.CONNECTION_ERROR);
|
||||
listenForFailure(ConnectionErrors.OTHER_ERRORS);
|
||||
|
||||
// install event listeners
|
||||
Object.keys(handlers).forEach(function (event) {
|
||||
connection.addEventListener(event, handlers[event]);
|
||||
});
|
||||
|
||||
connection.connect();
|
||||
}).catch(function (err) {
|
||||
if (err[0] === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
// FIXME ask for password and try again
|
||||
return connect();
|
||||
}
|
||||
console.error('FAILED TO CONNECT', err);
|
||||
APP.UI.notifyConnectionFailed(err[1]);
|
||||
|
||||
throw new Error(err[0]);
|
||||
});
|
||||
}
|
||||
|
||||
var ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
var ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
const ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
function initConference(localTracks, connection) {
|
||||
let room = connection.initJitsiConference(APP.conference.roomName, {
|
||||
openSctp: config.openSctp,
|
||||
|
@ -378,10 +330,6 @@ function initConference(localTracks, connection) {
|
|||
APP.UI.changeDisplayName(APP.conference.localId, nickname);
|
||||
});
|
||||
|
||||
room.on(ConferenceErrors.CONNECTION_ERROR, function () {
|
||||
// FIXME handle
|
||||
});
|
||||
|
||||
APP.UI.addListener(
|
||||
UIEvents.START_MUTED_CHANGED,
|
||||
function (startAudioMuted, startVideoMuted) {
|
||||
|
@ -461,7 +409,7 @@ function initConference(localTracks, connection) {
|
|||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AUTH_CLICKED, function () {
|
||||
// FIXME handle
|
||||
AuthHandler.authenticate(room);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, function (id) {
|
||||
|
@ -477,22 +425,67 @@ function initConference(localTracks, connection) {
|
|||
});
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, resolve);
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, handleConferenceJoined);
|
||||
room.on(ConferenceEvents.CONFERENCE_FAILED, onConferenceFailed);
|
||||
|
||||
room.on(ConferenceErrors.PASSWORD_REQUIRED, function () {
|
||||
APP.UI.markRoomLocked(true);
|
||||
roomLocker.requirePassword().then(function () {
|
||||
room.join(roomLocker.password);
|
||||
});
|
||||
});
|
||||
let password;
|
||||
let reconnectTimeout;
|
||||
|
||||
// FIXME handle errors here
|
||||
function unsubscribe() {
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_JOINED, handleConferenceJoined
|
||||
);
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_FAILED, onConferenceFailed
|
||||
);
|
||||
if (reconnectTimeout) {
|
||||
clearTimeout(reconnectTimeout);
|
||||
}
|
||||
AuthHandler.closeAuth();
|
||||
}
|
||||
|
||||
room.join();
|
||||
}).catch(function (err) {
|
||||
// FIXME notify that we cannot conenct to the room
|
||||
function handleConferenceJoined() {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
|
||||
throw new Error(err[0]);
|
||||
function handleConferenceFailed(err) {
|
||||
unsubscribe();
|
||||
reject(err);
|
||||
}
|
||||
|
||||
function onConferenceFailed(err, msg = '') {
|
||||
console.error('CONFERENCE FAILED:', err, msg);
|
||||
switch (err) {
|
||||
// room is locked by the password
|
||||
case ConferenceErrors.PASSWORD_REQUIRED:
|
||||
APP.UI.markRoomLocked(true);
|
||||
roomLocker.requirePassword().then(function () {
|
||||
room.join(roomLocker.password);
|
||||
});
|
||||
break;
|
||||
|
||||
case ConferenceErrors.CONNECTION_ERROR:
|
||||
APP.UI.notifyConnectionFailed(msg);
|
||||
break;
|
||||
|
||||
// not enough rights to create conference
|
||||
case ConferenceErrors.AUTHENTICATION_REQUIRED:
|
||||
// schedule reconnect to check if someone else created the room
|
||||
reconnectTimeout = setTimeout(function () {
|
||||
room.join(password);
|
||||
}, 5000);
|
||||
|
||||
// notify user that auth is required
|
||||
AuthHandler.requireAuth(APP.conference.roomName);
|
||||
break;
|
||||
|
||||
default:
|
||||
handleConferenceFailed(err);
|
||||
}
|
||||
}
|
||||
|
||||
room.join(password);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -505,9 +498,22 @@ function createLocalTracks () {
|
|||
});
|
||||
}
|
||||
|
||||
function connect() {
|
||||
return openConnection({retry: true}).catch(function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
APP.UI.notifyTokenAuthFailed();
|
||||
} else {
|
||||
APP.UI.notifyConnectionFailed(err);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
APP.UI.start();
|
||||
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
||||
|
||||
JitsiMeetJS.init().then(function () {
|
||||
return Promise.all([createLocalTracks(), connect()]);
|
||||
}).then(function ([tracks, connection]) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JitsiMeetJS = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
(function (__filename){
|
||||
/* global Strophe, $ */
|
||||
/* global Strophe, $, Promise */
|
||||
/* jshint -W101 */
|
||||
var logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
var RTC = require("./modules/RTC/RTC");
|
||||
|
@ -54,6 +54,13 @@ JitsiConference.prototype.join = function (password) {
|
|||
this.room.join(password, this.connection.tokenPassword);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if joined to the conference.
|
||||
*/
|
||||
JitsiConference.prototype.isJoined = function () {
|
||||
return this.room && this.room.joined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Leaves the conference.
|
||||
*/
|
||||
|
@ -63,6 +70,40 @@ JitsiConference.prototype.leave = function () {
|
|||
this.room = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns name of this conference.
|
||||
*/
|
||||
JitsiConference.prototype.getName = function () {
|
||||
return this.options.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if external authentication is enabled for this conference.
|
||||
*/
|
||||
JitsiConference.prototype.isExternalAuthEnabled = function () {
|
||||
return this.room && this.room.moderator.isExternalAuthEnabled();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get url for external authentication.
|
||||
* @param {boolean} [urlForPopup] if true then return url for login popup,
|
||||
* else url of login page.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
JitsiConference.prototype.getExternalAuthUrl = function (urlForPopup) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!this.isExternalAuthEnabled()) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
if (urlForPopup) {
|
||||
this.room.moderator.getPopupLoginUrl(resolve, reject);
|
||||
} else {
|
||||
this.room.moderator.getLoginUrl(resolve, reject);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the local tracks.
|
||||
*/
|
||||
|
@ -225,6 +266,11 @@ JitsiConference.prototype._fireMuteChangeEvent = function (track) {
|
|||
* @param track the JitsiLocalTrack object.
|
||||
*/
|
||||
JitsiConference.prototype.removeTrack = function (track) {
|
||||
if(!this.room){
|
||||
if(this.rtc)
|
||||
this.rtc.removeLocalStream(track);
|
||||
return;
|
||||
}
|
||||
this.room.removeStream(track.getOriginalStream(), function(){
|
||||
this.rtc.removeLocalStream(track);
|
||||
this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
|
||||
|
@ -264,7 +310,7 @@ JitsiConference.prototype.lock = function (password) {
|
|||
}, function (err) {
|
||||
reject(err);
|
||||
}, function () {
|
||||
reject(JitsiConferenceErrors.PASSWORD_REQUIRED);
|
||||
reject(JitsiConferenceErrors.PASSWORD_NOT_SUPPORTED);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -475,6 +521,18 @@ function setupListeners(conference) {
|
|||
conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
|
||||
});
|
||||
conference.room.addListener(XMPPEvents.ROOM_JOIN_ERROR, function (pres) {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONNECTION_ERROR, pres);
|
||||
});
|
||||
conference.room.addListener(XMPPEvents.ROOM_CONNECT_ERROR, function (pres) {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONNECTION_ERROR, pres);
|
||||
});
|
||||
conference.room.addListener(XMPPEvents.PASSWORD_REQUIRED, function (pres) {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.PASSWORD_REQUIRED, pres);
|
||||
});
|
||||
conference.room.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, function () {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.AUTHENTICATION_REQUIRED);
|
||||
});
|
||||
// FIXME
|
||||
// conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
|
||||
// conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT);
|
||||
|
@ -498,7 +556,7 @@ function setupListeners(conference) {
|
|||
conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_RESTORED);
|
||||
});
|
||||
conference.room.addListener(XMPPEvents.CONFERENCE_SETUP_FAILED, function () {
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED);
|
||||
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.SETUP_FAILED);
|
||||
});
|
||||
|
||||
conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) {
|
||||
|
@ -561,6 +619,10 @@ var JitsiConferenceErrors = {
|
|||
* Indicates that a password is required in order to join the conference.
|
||||
*/
|
||||
PASSWORD_REQUIRED: "conference.passwordRequired",
|
||||
/**
|
||||
* Indicates that client must be authenticated to create the conference.
|
||||
*/
|
||||
AUTHENTICATION_REQUIRED: "conference.authenticationRequired",
|
||||
/**
|
||||
* Indicates that password cannot be set for this conference.
|
||||
*/
|
||||
|
@ -570,6 +632,10 @@ var JitsiConferenceErrors = {
|
|||
* conference.
|
||||
*/
|
||||
CONNECTION_ERROR: "conference.connectionError",
|
||||
/**
|
||||
* Indicates that the conference setup failed.
|
||||
*/
|
||||
SETUP_FAILED: "conference.setup_failed",
|
||||
/**
|
||||
* Indicates that there is no available videobridge.
|
||||
*/
|
||||
|
@ -653,9 +719,9 @@ var JitsiConferenceEvents = {
|
|||
*/
|
||||
CONNECTION_RESTORED: "conference.connectionRestored",
|
||||
/**
|
||||
* Indicates that the conference setup failed.
|
||||
* Indicates that conference failed.
|
||||
*/
|
||||
SETUP_FAILED: "conference.setup_failed",
|
||||
CONFERENCE_FAILED: "conference.failed",
|
||||
/**
|
||||
* Indicates that conference has been joined.
|
||||
*/
|
||||
|
@ -1346,7 +1412,6 @@ function JitsiLocalTrack(stream, videoType,
|
|||
this.dontFireRemoveEvent = false;
|
||||
this.resolution = resolution;
|
||||
this.startMuted = false;
|
||||
this.isLocal = true;
|
||||
var self = this;
|
||||
JitsiTrack.call(this, null, stream,
|
||||
function () {
|
||||
|
@ -1517,7 +1582,6 @@ function JitsiRemoteTrack(RTC, data, sid, ssrc) {
|
|||
this.videoType = data.videoType;
|
||||
this.ssrc = ssrc;
|
||||
this.muted = false;
|
||||
this.isLocal = false;
|
||||
if((this.type === JitsiTrack.AUDIO && data.audiomuted)
|
||||
|| (this.type === JitsiTrack.VIDEO && data.videomuted)) {
|
||||
this.muted = true;
|
||||
|
@ -3391,9 +3455,8 @@ module.exports = ScreenObtainer;
|
|||
}).call(this,"/modules/RTC/ScreenObtainer.js")
|
||||
},{"../../service/desktopsharing/DesktopSharingEventTypes":82,"./RTCBrowserType":17,"./adapter.screenshare":20,"jitsi-meet-logger":47}],20:[function(require,module,exports){
|
||||
(function (__filename){
|
||||
/*! adapterjs - v0.12.0 - 2015-09-04 */
|
||||
/*! adapterjs - v0.12.3 - 2015-11-16 */
|
||||
var console = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
// Adapter's interface.
|
||||
var AdapterJS = AdapterJS || {};
|
||||
|
||||
|
@ -3411,7 +3474,7 @@ AdapterJS.options = AdapterJS.options || {};
|
|||
// AdapterJS.options.hidePluginInstallPrompt = true;
|
||||
|
||||
// AdapterJS version
|
||||
AdapterJS.VERSION = '0.12.0';
|
||||
AdapterJS.VERSION = '0.12.3';
|
||||
|
||||
// This function will be called when the WebRTC API is ready to be used
|
||||
// Whether it is the native implementation (Chrome, Firefox, Opera) or
|
||||
|
@ -4001,7 +4064,7 @@ if (navigator.mozGetUserMedia) {
|
|||
|
||||
createIceServers = function (urls, username, password) {
|
||||
var iceServers = [];
|
||||
for (i = 0; i < urls.length; i++) {
|
||||
for (var i = 0; i < urls.length; i++) {
|
||||
var iceServer = createIceServer(urls[i], username, password);
|
||||
if (iceServer !== null) {
|
||||
iceServers.push(iceServer);
|
||||
|
@ -4091,7 +4154,7 @@ if (navigator.mozGetUserMedia) {
|
|||
'username' : username
|
||||
};
|
||||
} else {
|
||||
for (i = 0; i < urls.length; i++) {
|
||||
for (var i = 0; i < urls.length; i++) {
|
||||
var iceServer = createIceServer(urls[i], username, password);
|
||||
if (iceServer !== null) {
|
||||
iceServers.push(iceServer);
|
||||
|
@ -4393,12 +4456,13 @@ if (navigator.mozGetUserMedia) {
|
|||
return;
|
||||
}
|
||||
|
||||
var streamId
|
||||
var streamId;
|
||||
if (stream === null) {
|
||||
streamId = '';
|
||||
}
|
||||
else {
|
||||
stream.enableSoundTracks(true); // TODO: remove on 0.12.0
|
||||
} else {
|
||||
if (typeof stream.enableSoundTracks !== 'undefined') {
|
||||
stream.enableSoundTracks(true);
|
||||
}
|
||||
streamId = stream.id;
|
||||
}
|
||||
|
||||
|
@ -4440,16 +4504,13 @@ if (navigator.mozGetUserMedia) {
|
|||
|
||||
var height = '';
|
||||
var width = '';
|
||||
if (element.getBoundingClientRect) {
|
||||
var rectObject = element.getBoundingClientRect();
|
||||
width = rectObject.width + 'px';
|
||||
height = rectObject.height + 'px';
|
||||
if (element.clientWidth || element.clientHeight) {
|
||||
width = element.clientWidth;
|
||||
height = element.clientHeight;
|
||||
}
|
||||
else if (element.width) {
|
||||
else if (element.width || element.height) {
|
||||
width = element.width;
|
||||
height = element.height;
|
||||
} else {
|
||||
// TODO: What scenario could bring us here?
|
||||
}
|
||||
|
||||
element.parentNode.insertBefore(frag, element);
|
||||
|
@ -4468,19 +4529,7 @@ if (navigator.mozGetUserMedia) {
|
|||
element.setStreamId(streamId);
|
||||
}
|
||||
var newElement = document.getElementById(elementId);
|
||||
newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
|
||||
newElement.onplay = (element.onplay) ? element.onplay : function (arg) {};
|
||||
newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
|
||||
if (isIE) { // on IE the event needs to be plugged manually
|
||||
newElement.attachEvent('onplaying', newElement.onplaying);
|
||||
newElement.attachEvent('onplay', newElement.onplay);
|
||||
newElement._TemOnClick = function (id) {
|
||||
var arg = {
|
||||
srcElement : document.getElementById(id)
|
||||
};
|
||||
newElement.onclick(arg);
|
||||
};
|
||||
}
|
||||
AdapterJS.forwardEventHandlers(newElement, element, Object.getPrototypeOf(element));
|
||||
|
||||
return newElement;
|
||||
};
|
||||
|
@ -4503,6 +4552,32 @@ if (navigator.mozGetUserMedia) {
|
|||
}
|
||||
};
|
||||
|
||||
AdapterJS.forwardEventHandlers = function (destElem, srcElem, prototype) {
|
||||
|
||||
properties = Object.getOwnPropertyNames( prototype );
|
||||
|
||||
for(prop in properties) {
|
||||
propName = properties[prop];
|
||||
|
||||
if (typeof(propName.slice) === 'function') {
|
||||
if (propName.slice(0,2) == 'on' && srcElem[propName] != null) {
|
||||
if (isIE) {
|
||||
destElem.attachEvent(propName,srcElem[propName]);
|
||||
} else {
|
||||
destElem.addEventListener(propName.slice(2), srcElem[propName], false)
|
||||
}
|
||||
} else {
|
||||
//TODO (http://jira.temasys.com.sg/browse/TWP-328) Forward non-event properties ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var subPrototype = Object.getPrototypeOf(prototype)
|
||||
if(subPrototype != null) {
|
||||
AdapterJS.forwardEventHandlers(destElem, srcElem, subPrototype);
|
||||
}
|
||||
}
|
||||
|
||||
RTCIceCandidate = function (candidate) {
|
||||
if (!candidate.sdpMid) {
|
||||
candidate.sdpMid = '';
|
||||
|
@ -9659,7 +9734,7 @@ function TraceablePeerConnection(ice_config, constraints, session) {
|
|||
var Interop = require('sdp-interop').Interop;
|
||||
this.interop = new Interop();
|
||||
var Simulcast = require('sdp-simulcast');
|
||||
this.simulcast = new Simulcast({numOfLayers: 2, explodeRemoteSimulcast: false});
|
||||
this.simulcast = new Simulcast({numOfLayers: 3, explodeRemoteSimulcast: false});
|
||||
|
||||
// override as desired
|
||||
this.trace = function (what, info) {
|
||||
|
@ -10441,7 +10516,7 @@ Moderator.prototype.allocateConferenceFocus = function (callback) {
|
|||
);
|
||||
};
|
||||
|
||||
Moderator.prototype.getLoginUrl = function (urlCallback) {
|
||||
Moderator.prototype.getLoginUrl = function (urlCallback, failureCallback) {
|
||||
var iq = $iq({to: this.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
|
@ -10459,14 +10534,17 @@ Moderator.prototype.getLoginUrl = function (urlCallback) {
|
|||
} else {
|
||||
logger.error(
|
||||
"Failed to get auth url from the focus", result);
|
||||
failureCallback(result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
logger.error("Get auth url error", error);
|
||||
failureCallback(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
Moderator.prototype.getPopupLoginUrl = function (urlCallback) {
|
||||
|
||||
Moderator.prototype.getPopupLoginUrl = function (urlCallback, failureCallback) {
|
||||
var iq = $iq({to: this.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
|
@ -10485,10 +10563,12 @@ Moderator.prototype.getPopupLoginUrl = function (urlCallback) {
|
|||
} else {
|
||||
logger.error(
|
||||
"Failed to get POPUP auth url from the focus", result);
|
||||
failureCallback(result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
logger.error('Get POPUP auth url error', error);
|
||||
failureCallback(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -10523,9 +10603,6 @@ Moderator.prototype.logout = function (callback) {
|
|||
|
||||
module.exports = Moderator;
|
||||
|
||||
|
||||
|
||||
|
||||
}).call(this,"/modules/xmpp/moderator.js")
|
||||
},{"../../service/authentication/AuthenticationEvents":81,"../../service/xmpp/XMPPEvents":85,"../settings/Settings":21,"jitsi-meet-logger":47}],35:[function(require,module,exports){
|
||||
(function (__filename){
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/* global JitsiMeetJS */
|
||||
|
||||
import LoginDialog from './UI/authentication/LoginDialog';
|
||||
import UIEvents from '../service/UI/UIEvents';
|
||||
import UIUtil from './UI/util/UIUtil';
|
||||
import {openConnection} from './connection';
|
||||
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
|
||||
let externalAuthWindow;
|
||||
let authRequiredDialog;
|
||||
|
||||
function doExternalAuth (room, lockPassword) {
|
||||
if (externalAuthWindow) {
|
||||
externalAuthWindow.focus();
|
||||
return;
|
||||
}
|
||||
if (room.isJoined()) {
|
||||
room.getExternalAuthUrl(true).then(function (url) {
|
||||
externalAuthWindow = LoginDialog.showExternalAuthDialog(
|
||||
url,
|
||||
function () {
|
||||
externalAuthWindow = null;
|
||||
room.join(lockPassword);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// If conference has not been started yet
|
||||
// then redirect to login page
|
||||
room.getExternalAuthUrl().then(UIUtil.redirect);
|
||||
}
|
||||
}
|
||||
|
||||
function doXmppAuth (room, lockPassword) {
|
||||
let loginDialog = LoginDialog.showAuthDialog(function (id, password) {
|
||||
// auth "on the fly":
|
||||
// 1. open new connection with proper id and password
|
||||
// 2. connect to the room
|
||||
// (this will store sessionId in the localStorage)
|
||||
// 3. close new connection
|
||||
// 4. reallocate focus in current room
|
||||
openConnection({id, password}).then(function (connection) {
|
||||
// open room
|
||||
let newRoom = connection.initJitsiConference(room.getName());
|
||||
|
||||
newRoom.on(ConferenceEvents.CONFERENCE_FAILED, function (err) {
|
||||
connection.disconnect();
|
||||
loginDialog.displayError(err);
|
||||
});
|
||||
// FIXME finish "on the fly" auth
|
||||
room.room.moderator.allocateConferenceFocus(function () {
|
||||
connection.disconnect();
|
||||
loginDialog.close();
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
loginDialog.displayError(err);
|
||||
});
|
||||
}, function () { // user canceled
|
||||
loginDialog.close();
|
||||
});
|
||||
}
|
||||
|
||||
function authenticate (room, lockPassword) {
|
||||
if (room.isExternalAuthEnabled()) {
|
||||
doExternalAuth(room, lockPassword);
|
||||
} else {
|
||||
doXmppAuth();
|
||||
}
|
||||
}
|
||||
|
||||
function requireAuth(roomName) {
|
||||
if (authRequiredDialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
authRequiredDialog = LoginDialog.showAuthRequiredDialog(
|
||||
roomName, authenticate
|
||||
);
|
||||
}
|
||||
|
||||
function closeAuth() {
|
||||
if (externalAuthWindow) {
|
||||
externalAuthWindow.close();
|
||||
externalAuthWindow = null;
|
||||
}
|
||||
|
||||
if (authRequiredDialog) {
|
||||
authRequiredDialog.close();
|
||||
authRequiredDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
authenticate,
|
||||
requireAuth,
|
||||
closeAuth
|
||||
};
|
|
@ -736,4 +736,8 @@ UI.updateRecordingState = function (state) {
|
|||
Toolbar.updateRecordingState(state);
|
||||
};
|
||||
|
||||
UI.notifyTokenAuthFailed = function () {
|
||||
messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
|
||||
};
|
||||
|
||||
module.exports = UI;
|
||||
|
|
|
@ -2,40 +2,39 @@
|
|||
|
||||
var messageHandler = require('../util/MessageHandler');
|
||||
|
||||
//FIXME: use LoginDialog to add retries to XMPP.connect method used when
|
||||
// anonymous domain is not enabled
|
||||
function getPasswordInputHtml() {
|
||||
let placeholder = config.hosts.authdomain
|
||||
? "user identity"
|
||||
: "user@domain.net";
|
||||
let passRequiredMsg = APP.translation.translateString(
|
||||
"dialog.passwordRequired"
|
||||
);
|
||||
return `
|
||||
<h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
|
||||
<input name="username" type="text" placeholder=${placeholder} autofocus>
|
||||
<input name="password" type="password"
|
||||
data-i18n="[placeholder]dialog.userPassword"
|
||||
placeholder="user password">
|
||||
`;
|
||||
}
|
||||
|
||||
function Dialog(successCallback, cancelCallback) {
|
||||
var message = '<h2 data-i18n="dialog.passwordRequired">';
|
||||
message += APP.translation.translateString("dialog.passwordRequired");
|
||||
message += '</h2>' +
|
||||
'<input name="username" type="text" ';
|
||||
if (config.hosts.authdomain) {
|
||||
message += 'placeholder="user identity" autofocus>';
|
||||
} else {
|
||||
message += 'placeholder="user@domain.net" autofocus>';
|
||||
}
|
||||
message += '<input name="password" ' +
|
||||
'type="password" data-i18n="[placeholder]dialog.userPassword"' +
|
||||
' placeholder="user password">';
|
||||
|
||||
var okButton = APP.translation.generateTranslationHTML("dialog.Ok");
|
||||
|
||||
var cancelButton = APP.translation.generateTranslationHTML("dialog.Cancel");
|
||||
|
||||
var states = {
|
||||
const states = {
|
||||
login: {
|
||||
html: message,
|
||||
buttons: [
|
||||
{ title: okButton, value: true},
|
||||
{ title: cancelButton, value: false}
|
||||
],
|
||||
html: getPasswordInputHtml(),
|
||||
buttons: [{
|
||||
title: APP.translation.generateTranslationHTML("dialog.Ok"),
|
||||
value: true
|
||||
}, {
|
||||
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
|
||||
value: false
|
||||
}],
|
||||
focus: ':input:first',
|
||||
submit: function (e, v, m, f) {
|
||||
e.preventDefault();
|
||||
if (v) {
|
||||
var jid = f.username;
|
||||
var password = f.password;
|
||||
let jid = f.username;
|
||||
let password = f.password;
|
||||
if (jid && password) {
|
||||
connDialog.goToState('connecting');
|
||||
successCallback(jid, password);
|
||||
|
@ -55,22 +54,20 @@ function Dialog(successCallback, cancelCallback) {
|
|||
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'
|
||||
},
|
||||
],
|
||||
buttons: [{
|
||||
title: APP.translation.translateString('dialog.retry'),
|
||||
value: 'retry'
|
||||
}, {
|
||||
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
|
||||
value: false
|
||||
}],
|
||||
defaultButton: 0,
|
||||
submit: function (e, v, m, f) {
|
||||
e.preventDefault();
|
||||
if (v === 'retry') {
|
||||
connDialog.goToState('login');
|
||||
} else {
|
||||
// User cancelled
|
||||
cancelCallback();
|
||||
}
|
||||
}
|
||||
|
@ -104,23 +101,9 @@ function Dialog(successCallback, cancelCallback) {
|
|||
};
|
||||
}
|
||||
|
||||
var LoginDialog = {
|
||||
const 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 (successCallback, cancelCallback) {
|
||||
showAuthDialog: function (successCallback, cancelCallback) {
|
||||
return new Dialog(successCallback, cancelCallback);
|
||||
},
|
||||
|
||||
|
@ -156,10 +139,10 @@ var LoginDialog = {
|
|||
msg,
|
||||
true,
|
||||
buttons,
|
||||
function (onSubmitEvent, submitValue) {
|
||||
function (e, submitValue) {
|
||||
|
||||
// Do not close the dialog yet
|
||||
onSubmitEvent.preventDefault();
|
||||
e.preventDefault();
|
||||
|
||||
// Open login popup
|
||||
if (submitValue === 'authNow') {
|
||||
|
@ -170,4 +153,4 @@ var LoginDialog = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = LoginDialog;
|
||||
export default LoginDialog;
|
||||
|
|
|
@ -114,7 +114,11 @@ import PanelToggler from "../side_pannels/SidePanelToggler";
|
|||
.filter(function (item) { return item; })
|
||||
.join(',');
|
||||
$(selector).hide();
|
||||
}
|
||||
},
|
||||
|
||||
redirect (url) {
|
||||
window.location.href = url;
|
||||
}
|
||||
};
|
||||
|
||||
export default UIUtil;
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* global APP, JitsiMeetJS, config */
|
||||
|
||||
import LoginDialog from './UI/authentication/LoginDialog';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
export function openConnection({retry, id, password}) {
|
||||
let connection = new JitsiMeetJS.JitsiConnection(null, null, {
|
||||
hosts: config.hosts,
|
||||
bosh: config.bosh,
|
||||
clientNode: config.clientNode
|
||||
});
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
connection.addEventListener(
|
||||
ConnectionEvents.CONNECTION_ESTABLISHED, handleConnectionEstablished
|
||||
);
|
||||
connection.addEventListener(
|
||||
ConnectionEvents.CONNECTION_FAILED, onConnectionFailed
|
||||
);
|
||||
let authDialog;
|
||||
|
||||
function unsubscribe() {
|
||||
connection.removeEventListener(
|
||||
ConnectionEvents.CONNECTION_ESTABLISHED,
|
||||
handleConnectionEstablished
|
||||
);
|
||||
connection.removeEventListener(
|
||||
ConnectionEvents.CONNECTION_FAILED, onConnectionFailed
|
||||
);
|
||||
if (authDialog) {
|
||||
authDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
function handleConnectionEstablished() {
|
||||
unsubscribe();
|
||||
resolve(connection);
|
||||
}
|
||||
|
||||
function handleConnectionFailed(err) {
|
||||
unsubscribe();
|
||||
reject(err);
|
||||
}
|
||||
|
||||
function onConnectionFailed (err) {
|
||||
console.error("CONNECTION FAILED:", err);
|
||||
|
||||
if (!retry) {
|
||||
handleConnectionFailed(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// retry only if auth failed
|
||||
if (err !== ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
handleConnectionFailed(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// do not retry if token is not valid
|
||||
if (config.token) {
|
||||
handleConnectionFailed(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// ask for password and try again
|
||||
|
||||
if (authDialog) {
|
||||
authDialog.displayError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
authDialog = LoginDialog.showAuthDialog(
|
||||
function (id, password) {
|
||||
connection.connect({id, password});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
connection.connect(id, password);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue