Commit ac1dc77b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Reconnect when server complains about a username.

If a token does not specify a username, the server will request
one by failing the join message.  Disconnect from the WebSocket
in that case, and display the login dialog with the password
field invisible.
parent 4c9e00d8
......@@ -105,9 +105,11 @@
<label for="username">Username</label>
<input id="username" type="text" name="username"
autocomplete="username" class="form-control"/>
<label for="password">Password</label>
<input id="password" type="password" name="password"
autocomplete="current-password" class="form-control"/>
<div id="passwordform">
<label for="password">Password</label>
<input id="password" type="password" name="password"
autocomplete="current-password" class="form-control"/>
</div>
<label>Enable at start:</label>
<div class="present-switch">
<p class="switch-radio">
......
......@@ -32,6 +32,9 @@ let groupStatus = {};
/** @type {string} */
let token = null;
/** @type {boolean} */
let connectingAgain = false;
/**
* @typedef {Object} settings
* @property {boolean} [localMute]
......@@ -289,27 +292,39 @@ function setConnected(connected) {
} else {
userbox.classList.add('invisible');
connectionbox.classList.remove('invisible');
displayError('Disconnected', 'error');
if(!connectingAgain)
displayError('Disconnected', 'error');
hideVideo();
window.onresize = null;
}
}
/**
* @this {ServerConnection}
*/
* @this {ServerConnection}
*/
async function gotConnected() {
let username, credentials;
setConnected(true);
let again = connectingAgain;
connectingAgain = false;
await join(again);
}
/**
* @param {boolean} again
*/
async function join(again) {
let username = getInputElement('username').value.trim();
let credentials;
if(token) {
credentials = {
type: 'token',
token: token,
};
token = null;
if(!again)
// the first time around, we need to join with no username in
// order to give the server a chance to reply with 'need-username'.
username = null;
} else {
setConnected(true);
username = getInputElement('username').value.trim();
let pw = getInputElement('password').value;
getInputElement('password').value = '';
if(!groupStatus.authServer)
......@@ -324,7 +339,7 @@ async function gotConnected() {
}
try {
await this.join(group, username, credentials);
await serverConnection.join(group, username, credentials);
} catch(e) {
console.error(e);
displayError(e);
......@@ -2314,29 +2329,42 @@ function setTitle(title) {
* @param {Array<string>} perms
* @param {Object<string,any>} status
* @param {Object<string,any>} data
* @param {string} error
* @param {string} message
*/
async function gotJoined(kind, group, perms, status, data, message) {
async function gotJoined(kind, group, perms, status, data, error, message) {
let present = presentRequested;
presentRequested = null;
switch(kind) {
case 'fail':
displayError('The server said: ' + message);
if(error === 'need-username' || error === 'duplicate-username') {
setVisibility('passwordform', false);
connectingAgain = true;
} else {
token = null;
}
if(error !== 'need-username')
displayError('The server said: ' + message);
this.close();
setButtonsVisibility();
return;
case 'redirect':
this.close();
token = null;
document.location.href = message;
return;
case 'leave':
this.close();
token = null;
setButtonsVisibility();
return;
case 'join':
case 'change':
groupStatus = status;
token = null;
// don't discard endPoint and friends
for(let key in status)
groupStatus[key] = status[key];
setTitle((status && status.displayName) || capitalise(group));
displayUsername();
setButtonsVisibility();
......@@ -2344,11 +2372,14 @@ async function gotJoined(kind, group, perms, status, data, message) {
return;
break;
default:
token = null;
displayError('Unknown join message');
this.close();
return;
}
token = null;
let input = /** @type{HTMLTextAreaElement} */
(document.getElementById('input'));
input.placeholder = 'Type /help for help';
......@@ -3622,12 +3653,8 @@ document.getElementById('userform').onsubmit = async function(e) {
e.preventDefault();
if(connecting)
return;
connecting = true;
try {
await serverConnect();
} finally {
connecting = false;
}
setVisibility('passwordform', true);
if(getInputElement('presentboth').checked)
presentRequested = 'both';
......@@ -3635,8 +3662,15 @@ document.getElementById('userform').onsubmit = async function(e) {
presentRequested = 'mike';
else
presentRequested = null;
getInputElement('presentoff').checked = true;
// Connect to the server, gotConnected will join.
connecting = true;
try {
await serverConnect();
} finally {
connecting = false;
}
};
document.getElementById('disconnectbutton').onclick = function(e) {
......@@ -3759,14 +3793,15 @@ async function start() {
addFilters();
setMediaChoices(false).then(e => reflectSettings());
if(parms.has('token')) {
if(parms.has('token'))
token = parms.get('token');
if(token) {
await serverConnect();
} else if(groupStatus.authPortal) {
window.location.href = groupStatus.authPortal;
} else {
let container = document.getElementById("login-container");
container.classList.remove('invisible');
setVisibility('login-container', true);
}
setViewportHeight();
}
......
......@@ -179,7 +179,7 @@ function ServerConnection() {
*
* kind is one of 'join', 'fail', 'change' or 'leave'.
*
* @type{(this: ServerConnection, kind: string, group: string, permissions: Array<string>, status: Object<string,any>, data: Object<string,any>, message: string) => void}
* @type{(this: ServerConnection, kind: string, group: string, permissions: Array<string>, status: Object<string,any>, data: Object<string,any>, error: string, message: string) => void}
*/
this.onjoined = null;
/**
......@@ -321,7 +321,7 @@ ServerConnection.prototype.connect = async function(url) {
sc.onuser.call(sc, id, 'delete');
}
if(sc.group && sc.onjoined)
sc.onjoined.call(sc, 'leave', sc.group, [], {}, {}, '');
sc.onjoined.call(sc, 'leave', sc.group, [], {}, {}, '', '');
sc.group = null;
sc.username = null;
if(sc.onclose)
......@@ -393,7 +393,7 @@ ServerConnection.prototype.connect = async function(url) {
sc.onjoined.call(sc, m.kind, m.group,
m.permissions || [],
m.status, m.data,
m.value || null);
m.error || null, m.value || null);
break;
case 'user':
switch(m.kind) {
......@@ -505,8 +505,10 @@ ServerConnection.prototype.join = async function(group, username, credentials, d
type: 'join',
kind: 'join',
group: group,
username: username,
};
if(typeof username !== 'undefined' && username !== null)
m.username = username;
if((typeof credentials) === 'string') {
m.password = credentials;
} else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment