1
Fork 0

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.
This commit is contained in:
Juliusz Chroboczek 2023-04-01 13:28:24 +02:00
parent 4c9e00d874
commit ac1dc77b30
3 changed files with 68 additions and 29 deletions

View File

@ -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">

View File

@ -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) {
} 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) {
* @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() {
} }
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) {
* @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) {
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) {
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) {
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() {
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();
} }

View File

@ -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) {
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) {
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
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 {