-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
authenticateAndUpgradeRole.js
167 lines (147 loc) · 6.23 KB
/
authenticateAndUpgradeRole.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { getLogger } from '@jitsi/logger';
import {
CONNECTION_DISCONNECTED,
CONNECTION_ESTABLISHED,
CONNECTION_FAILED
} from './JitsiConnectionEvents';
import XMPP from './modules/xmpp/xmpp';
const logger = getLogger(__filename);
/**
* @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.onCreateResource]
* @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 <tt>thenable</tt> which (1) settles when the process of
* authenticating and upgrading the role of the specified XMPP user finishes and
* (2) has a <tt>cancel</tt> 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 <tt>thenable</tt> is resolved. If the process
* finishes with failure, the <tt>thenable</tt> is rejected with reason of type
* {@link UpgradeRoleError} which will have either <tt>connectionError</tt> or
* <tt>authenticationError</tt> property set depending on which of the steps has
* failed. If <tt>cancel</tt> 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.xmpp.moderator.authenticate(room.roomjid)
.then(() => {
xmpp && xmpp.disconnect();
if (canceled) {
return;
}
// we execute this logic in JitsiConference where we bind the current conference as `this`
// At this point we should have the new session ID
// stored in the settings. Send a new conference IQ.
this.room.xmpp.moderator.sendConferenceRequest(this.room.roomjid)
.catch(e => logger.trace('sendConferenceRequest rejected', e))
.finally(() => {
// we need to reset it because of breakout rooms which will
// reuse connection but will invite jicofo
this.room.xmpp.moderator.conferenceRequestSent = false;
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 */