From ac1dc77b304eeed580a642f04dfa44c65ebbe103 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 1 Apr 2023 13:28:24 +0200 Subject: [PATCH] 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. --- static/galene.html | 8 +++-- static/galene.js | 79 +++++++++++++++++++++++++++++++++------------- static/protocol.js | 10 +++--- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/static/galene.html b/static/galene.html index a5d464e..8ffe699 100644 --- a/static/galene.html +++ b/static/galene.html @@ -105,9 +105,11 @@ - - +
+ + +

diff --git a/static/galene.js b/static/galene.js index 4747f13..411366b 100644 --- a/static/galene.js +++ b/static/galene.js @@ -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} perms * @param {Object} status * @param {Object} 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(); } diff --git a/static/protocol.js b/static/protocol.js index 89b5701..3dfb3b3 100644 --- a/static/protocol.js +++ b/static/protocol.js @@ -179,7 +179,7 @@ function ServerConnection() { * * kind is one of 'join', 'fail', 'change' or 'leave'. * - * @type{(this: ServerConnection, kind: string, group: string, permissions: Array, status: Object, data: Object, message: string) => void} + * @type{(this: ServerConnection, kind: string, group: string, permissions: Array, status: Object, data: Object, 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 {