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 @@ ...@@ -105,9 +105,11 @@
<label for="username">Username</label> <label for="username">Username</label>
<input id="username" type="text" name="username" <input id="username" type="text" name="username"
autocomplete="username" class="form-control"/> autocomplete="username" class="form-control"/>
<div id="passwordform">
<label for="password">Password</label> <label for="password">Password</label>
<input id="password" type="password" name="password" <input id="password" type="password" name="password"
autocomplete="current-password" class="form-control"/> autocomplete="current-password" class="form-control"/>
</div>
<label>Enable at start:</label> <label>Enable at start:</label>
<div class="present-switch"> <div class="present-switch">
<p class="switch-radio"> <p class="switch-radio">
......
...@@ -32,6 +32,9 @@ let groupStatus = {}; ...@@ -32,6 +32,9 @@ let groupStatus = {};
/** @type {string} */ /** @type {string} */
let token = null; let token = null;
/** @type {boolean} */
let connectingAgain = false;
/** /**
* @typedef {Object} settings * @typedef {Object} settings
* @property {boolean} [localMute] * @property {boolean} [localMute]
...@@ -289,6 +292,7 @@ function setConnected(connected) { ...@@ -289,6 +292,7 @@ function setConnected(connected) {
} else { } else {
userbox.classList.add('invisible'); userbox.classList.add('invisible');
connectionbox.classList.remove('invisible'); connectionbox.classList.remove('invisible');
if(!connectingAgain)
displayError('Disconnected', 'error'); displayError('Disconnected', 'error');
hideVideo(); hideVideo();
window.onresize = null; window.onresize = null;
...@@ -299,17 +303,28 @@ function setConnected(connected) { ...@@ -299,17 +303,28 @@ function setConnected(connected) {
* @this {ServerConnection} * @this {ServerConnection}
*/ */
async function gotConnected() { 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) { if(token) {
credentials = { credentials = {
type: 'token', type: 'token',
token: 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 { } else {
setConnected(true);
username = getInputElement('username').value.trim();
let pw = getInputElement('password').value; let pw = getInputElement('password').value;
getInputElement('password').value = ''; getInputElement('password').value = '';
if(!groupStatus.authServer) if(!groupStatus.authServer)
...@@ -324,7 +339,7 @@ async function gotConnected() { ...@@ -324,7 +339,7 @@ async function gotConnected() {
} }
try { try {
await this.join(group, username, credentials); await serverConnection.join(group, username, credentials);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
displayError(e); displayError(e);
...@@ -2314,29 +2329,42 @@ function setTitle(title) { ...@@ -2314,29 +2329,42 @@ function setTitle(title) {
* @param {Array<string>} perms * @param {Array<string>} perms
* @param {Object<string,any>} status * @param {Object<string,any>} status
* @param {Object<string,any>} data * @param {Object<string,any>} data
* @param {string} error
* @param {string} message * @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; let present = presentRequested;
presentRequested = null; presentRequested = null;
switch(kind) { switch(kind) {
case 'fail': case 'fail':
if(error === 'need-username' || error === 'duplicate-username') {
setVisibility('passwordform', false);
connectingAgain = true;
} else {
token = null;
}
if(error !== 'need-username')
displayError('The server said: ' + message); displayError('The server said: ' + message);
this.close(); this.close();
setButtonsVisibility(); setButtonsVisibility();
return; return;
case 'redirect': case 'redirect':
this.close(); this.close();
token = null;
document.location.href = message; document.location.href = message;
return; return;
case 'leave': case 'leave':
this.close(); this.close();
token = null;
setButtonsVisibility(); setButtonsVisibility();
return; return;
case 'join': case 'join':
case 'change': 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)); setTitle((status && status.displayName) || capitalise(group));
displayUsername(); displayUsername();
setButtonsVisibility(); setButtonsVisibility();
...@@ -2344,11 +2372,14 @@ async function gotJoined(kind, group, perms, status, data, message) { ...@@ -2344,11 +2372,14 @@ async function gotJoined(kind, group, perms, status, data, message) {
return; return;
break; break;
default: default:
token = null;
displayError('Unknown join message'); displayError('Unknown join message');
this.close(); this.close();
return; return;
} }
token = null;
let input = /** @type{HTMLTextAreaElement} */ let input = /** @type{HTMLTextAreaElement} */
(document.getElementById('input')); (document.getElementById('input'));
input.placeholder = 'Type /help for help'; input.placeholder = 'Type /help for help';
...@@ -3622,12 +3653,8 @@ document.getElementById('userform').onsubmit = async function(e) { ...@@ -3622,12 +3653,8 @@ document.getElementById('userform').onsubmit = async function(e) {
e.preventDefault(); e.preventDefault();
if(connecting) if(connecting)
return; return;
connecting = true;
try { setVisibility('passwordform', true);
await serverConnect();
} finally {
connecting = false;
}
if(getInputElement('presentboth').checked) if(getInputElement('presentboth').checked)
presentRequested = 'both'; presentRequested = 'both';
...@@ -3635,8 +3662,15 @@ document.getElementById('userform').onsubmit = async function(e) { ...@@ -3635,8 +3662,15 @@ document.getElementById('userform').onsubmit = async function(e) {
presentRequested = 'mike'; presentRequested = 'mike';
else else
presentRequested = null; presentRequested = null;
getInputElement('presentoff').checked = true; 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) { document.getElementById('disconnectbutton').onclick = function(e) {
...@@ -3759,14 +3793,15 @@ async function start() { ...@@ -3759,14 +3793,15 @@ async function start() {
addFilters(); addFilters();
setMediaChoices(false).then(e => reflectSettings()); setMediaChoices(false).then(e => reflectSettings());
if(parms.has('token')) { if(parms.has('token'))
token = parms.get('token'); token = parms.get('token');
if(token) {
await serverConnect(); await serverConnect();
} else if(groupStatus.authPortal) { } else if(groupStatus.authPortal) {
window.location.href = groupStatus.authPortal; window.location.href = groupStatus.authPortal;
} else { } else {
let container = document.getElementById("login-container"); setVisibility('login-container', true);
container.classList.remove('invisible');
} }
setViewportHeight(); setViewportHeight();
} }
......
...@@ -179,7 +179,7 @@ function ServerConnection() { ...@@ -179,7 +179,7 @@ function ServerConnection() {
* *
* kind is one of 'join', 'fail', 'change' or 'leave'. * 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; this.onjoined = null;
/** /**
...@@ -321,7 +321,7 @@ ServerConnection.prototype.connect = async function(url) { ...@@ -321,7 +321,7 @@ ServerConnection.prototype.connect = async function(url) {
sc.onuser.call(sc, id, 'delete'); sc.onuser.call(sc, id, 'delete');
} }
if(sc.group && sc.onjoined) if(sc.group && sc.onjoined)
sc.onjoined.call(sc, 'leave', sc.group, [], {}, {}, ''); sc.onjoined.call(sc, 'leave', sc.group, [], {}, {}, '', '');
sc.group = null; sc.group = null;
sc.username = null; sc.username = null;
if(sc.onclose) if(sc.onclose)
...@@ -393,7 +393,7 @@ ServerConnection.prototype.connect = async function(url) { ...@@ -393,7 +393,7 @@ ServerConnection.prototype.connect = async function(url) {
sc.onjoined.call(sc, m.kind, m.group, sc.onjoined.call(sc, m.kind, m.group,
m.permissions || [], m.permissions || [],
m.status, m.data, m.status, m.data,
m.value || null); m.error || null, m.value || null);
break; break;
case 'user': case 'user':
switch(m.kind) { switch(m.kind) {
...@@ -505,8 +505,10 @@ ServerConnection.prototype.join = async function(group, username, credentials, d ...@@ -505,8 +505,10 @@ ServerConnection.prototype.join = async function(group, username, credentials, d
type: 'join', type: 'join',
kind: 'join', kind: 'join',
group: group, group: group,
username: username,
}; };
if(typeof username !== 'undefined' && username !== null)
m.username = username;
if((typeof credentials) === 'string') { if((typeof credentials) === 'string') {
m.password = credentials; m.password = credentials;
} else { } 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