import { CONNECTION_DISCONNECTED, CONNECTION_ESTABLISHED, CONNECTION_FAILED } from './JitsiConnectionEvents'; import XMPP from './modules/xmpp/xmpp'; /** * @typedef {Object} UpgradeRoleError * * @property {JitsiConnectionErrors} [connectionError] - One of * {@link JitsiConnectionErrors} which occurred when trying to connect to the * XMPP server. * @property {String} [authenticationError] - One of XMPP error conditions * returned by Jicofo on authentication attempt. See * {@link https://xmpp.org/rfcs/rfc3920.html#streams-error}. * @property {String} [message] - More details about the error. * @property {Object} [credentials] - The credentials that failed the * authentication. * @property {String} [credentials.jid] - The XMPP ID part of the credentials * that failed the authentication. * @property {string} [credentials.password] - The password part of the * credentials that failed the authentication. * * NOTE If neither one of the errors is present, then the operation has been * canceled. */ /* eslint-disable no-invalid-this */ /** * Connects to the XMPP server using the specified credentials and contacts * Jicofo in order to obtain a session ID (which is then stored in the local * storage). The user's role of the parent conference will be upgraded to * moderator (by Jicofo). It's also used to join the conference when starting * from anonymous domain and only authenticated users are allowed to create new * rooms. * * @param {Object} options * @param {string} options.id - XMPP user's ID to log in. For example, * user@xmpp-server.com. * @param {string} options.password - XMPP user's password to log in with. * @param {Function} [options.onLoginSuccessful] - Callback called when logging * into the XMPP server was successful. The next step will be to obtain a new * session ID from Jicofo and join the MUC using it which will effectively * upgrade the user's role to moderator. * @returns {Object} A thenable which (1) settles when the process of * authenticating and upgrading the role of the specified XMPP user finishes and * (2) has a cancel method that allows the caller to interrupt the * process. If the process finishes successfully, the session ID has been stored * in the settings and the thenable is resolved. If the process * finishes with failure, the thenable is rejected with reason of type * {@link UpgradeRoleError} which will have either connectionError or * authenticationError property set depending on which of the steps has * failed. If cancel is called before the process finishes, then the * thenable will be rejected with an empty object (i.e. no error property will * be set on the rejection reason). */ export default function authenticateAndUpgradeRole({ // 1. Log the specified XMPP user in. id, password, onCreateResource, // 2. Let the API client/consumer know as soon as the XMPP user has been // successfully logged in. onLoginSuccessful }) { let canceled = false; let rejectPromise; let xmpp = new XMPP(this.connection.options); const process = new Promise((resolve, reject) => { // The process is represented by a Thenable with a cancel method. The // Thenable is implemented using Promise and the cancel using the // Promise's reject function. rejectPromise = reject; xmpp.addListener( CONNECTION_DISCONNECTED, () => { xmpp = undefined; }); xmpp.addListener( CONNECTION_ESTABLISHED, () => { if (canceled) { return; } // Let the caller know that the XMPP login was successful. onLoginSuccessful && onLoginSuccessful(); // Now authenticate with Jicofo and get a new session ID. const room = xmpp.createRoom( this.options.name, this.options.config, onCreateResource ); room.moderator.authenticate() .then(() => { xmpp && xmpp.disconnect(); if (canceled) { return; } // At this point we should have the new session ID // stored in the settings. Send a new conference IQ. this.room.moderator.allocateConferenceFocus(); resolve(); }) .catch(({ error, message }) => { xmpp.disconnect(); reject({ authenticationError: error, message }); }); }); xmpp.addListener( CONNECTION_FAILED, (connectionError, message, credentials) => { reject({ connectionError, credentials, message }); xmpp = undefined; }); canceled || xmpp.connect(id, password); }); /** * Cancels the process, if it's in progress, of authenticating and upgrading * the role of the local participant/user. * * @public * @returns {void} */ process.cancel = () => { canceled = true; rejectPromise({}); xmpp && xmpp.disconnect(); }; return process; } /* eslint-enable no-invalid-this */