Fix race conditions
This commit is contained in:
parent
aa0351fb2d
commit
b24b36adec
7 changed files with 219 additions and 130 deletions
|
|
@ -121,7 +121,7 @@
|
|||
"placeholder.username": "cat name",
|
||||
"placeholder.captcha.code": "captcha code",
|
||||
"placeholder.message.input": "meow...",
|
||||
"desc.messages.encryption.active": "meows are end-to-end encrypted :3",
|
||||
"desc.messages.loading": "loading meows...",
|
||||
"desc.no.dms": "no direct meowchats :c",
|
||||
"action.dm.opening": "opening meowchat...",
|
||||
"dm.open.failed": "failed to open meowchat :c",
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@
|
|||
"placeholder.username": "username",
|
||||
"placeholder.captcha.code": "captcha code",
|
||||
"placeholder.message.input": "Message...",
|
||||
"desc.messages.encryption.active": "Messages are end-to-end encrypted",
|
||||
"desc.messages.loading": "Fetching messages...",
|
||||
"desc.no.dms": "No direct messages",
|
||||
"action.dm.opening": "Opening DM...",
|
||||
"dm.open.failed": "Failed to open DM",
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@
|
|||
async function start() {
|
||||
updateLoadingStatus("loading.loading");
|
||||
try {
|
||||
gotoHome();
|
||||
if (host != null)
|
||||
{
|
||||
await updateProtocolAndUrl(host);
|
||||
|
|
@ -109,6 +108,7 @@
|
|||
//if fails continue loading encryption may be broken
|
||||
console.error(e);
|
||||
}
|
||||
gotoHome();
|
||||
} else {
|
||||
showBlahNotification("error:auth.failed.redirect.to.login");
|
||||
await delay(2000);
|
||||
|
|
|
|||
167
webroot/main.js
167
webroot/main.js
|
|
@ -468,29 +468,49 @@ async function decryptString(base64Text, passphrase) {
|
|||
}
|
||||
|
||||
|
||||
let requestMutex = Promise.resolve();
|
||||
|
||||
async function fetchPost(url, value) {
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
body: value,
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
let release;
|
||||
const lock = new Promise(resolve => release = resolve);
|
||||
const prevMutex = requestMutex;
|
||||
requestMutex = prevMutex.then(() => lock);
|
||||
await prevMutex;
|
||||
try {
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
body: value,
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchPostEnc(url, value) {
|
||||
let nonce = await getNonce(id, passwordHash);
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
body: await encryptWithNonce(value, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
let release;
|
||||
const lock = new Promise(resolve => release = resolve);
|
||||
const prevMutex = requestMutex;
|
||||
requestMutex = prevMutex.then(() => lock);
|
||||
await prevMutex;
|
||||
try {
|
||||
let nonce = await getNonce(id, passwordHash);
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
body: await encryptWithNonce(value, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchAsync(url) {
|
||||
|
|
@ -503,15 +523,24 @@ async function fetchAsync(url) {
|
|||
}
|
||||
|
||||
async function fetchAsyncWAuth(url) {
|
||||
let response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
|
||||
}
|
||||
});
|
||||
let release;
|
||||
const lock = new Promise(resolve => release = resolve);
|
||||
const prevMutex = requestMutex;
|
||||
requestMutex = prevMutex.then(() => lock);
|
||||
await prevMutex;
|
||||
try {
|
||||
let response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
|
||||
}
|
||||
});
|
||||
|
||||
let data = await response.text();
|
||||
return data;
|
||||
let data = await response.text();
|
||||
return data;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
async function getServerInfo(host) {
|
||||
|
|
@ -520,48 +549,64 @@ async function getServerInfo(host) {
|
|||
}
|
||||
|
||||
async function Auth(loginUsername, loginPassword) {
|
||||
let resolvedId = await fetchAsync(`${url}/nametoid?u=${loginUsername}`);
|
||||
if (!resolvedId || resolvedId.trim() === "" || resolvedId.startsWith("error:")) {
|
||||
return "error:invalid.username.or.password";
|
||||
}
|
||||
let actualId = resolvedId.split(":")[0];
|
||||
|
||||
let passwordHash = await hashSHA3_512(loginPassword);
|
||||
let response = await fetch(`${url}/auth?id=${actualId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(actualId, passwordHash))
|
||||
let release;
|
||||
const lock = new Promise(resolve => release = resolve);
|
||||
const prevMutex = requestMutex;
|
||||
requestMutex = prevMutex.then(() => lock);
|
||||
await prevMutex;
|
||||
try {
|
||||
let resolvedId = await fetchAsync(`${url}/nametoid?u=${loginUsername}`);
|
||||
if (!resolvedId || resolvedId.trim() === "" || resolvedId.startsWith("error:")) {
|
||||
return "error:invalid.username.or.password";
|
||||
}
|
||||
});
|
||||
let actualId = resolvedId.split(":")[0];
|
||||
|
||||
let data = await response.text();
|
||||
if (data.startsWith("success:")) {
|
||||
data += "|" + actualId;
|
||||
let passwordHash = await hashSHA3_512(loginPassword);
|
||||
let response = await fetch(`${url}/auth?id=${actualId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(actualId, passwordHash))
|
||||
}
|
||||
});
|
||||
|
||||
let data = await response.text();
|
||||
if (data.startsWith("success:")) {
|
||||
data += "|" + actualId;
|
||||
}
|
||||
return data;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function fetchEncrypted(request, body = "") {
|
||||
let release;
|
||||
const lock = new Promise(resolve => release = resolve);
|
||||
const prevMutex = requestMutex;
|
||||
requestMutex = prevMutex.then(() => lock);
|
||||
await prevMutex;
|
||||
try {
|
||||
let nonce = await getNonce(id, passwordHash);
|
||||
|
||||
let nonce = await getNonce(id, passwordHash);
|
||||
let response = await fetch(`${url}/encryptedrequest?id=${id}`, {
|
||||
method: "POST",
|
||||
body: await encryptWithNonce(
|
||||
JSON.stringify({
|
||||
string1: request,
|
||||
string2: body
|
||||
})
|
||||
|
||||
let response = await fetch(`${url}/encryptedrequest?id=${id}`, {
|
||||
method: "POST",
|
||||
body: await encryptWithNonce(
|
||||
JSON.stringify({
|
||||
string1: request,
|
||||
string2: body
|
||||
})
|
||||
|
||||
, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return decryptString(data, passwordHash);
|
||||
, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return await decryptString(data, passwordHash);
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
function power(base, exponent, mod) {
|
||||
|
|
@ -1807,7 +1852,7 @@ async function openDm(dmId, username, targetId) {
|
|||
|
||||
let msgContainer = document.getElementById("chat-messages");
|
||||
if (msgContainer) {
|
||||
msgContainer.innerHTML = `<div style="text-align: center; opacity: 0.5; padding: 1rem;"><blah>desc.messages.encryption.active</blah></div>`;
|
||||
msgContainer.innerHTML = `<div style="text-align: center; opacity: 0.5; padding: 1rem;"><blah>desc.messages.loading</blah></div>`;
|
||||
let blahTags = msgContainer.getElementsByTagName("blah");
|
||||
for (let i = 0; i < blahTags.length; i++) {
|
||||
blahTags[i].innerHTML = processBlah(blahTags[i].innerHTML);
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ var invitesEntry = `
|
|||
var chatScreen = `
|
||||
<div style="display: flex; flex-direction: column; height: 100%; width: 100%;">
|
||||
<div id="chat-messages" style="flex-grow: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 0.5rem;">
|
||||
<!-- messages go here -->
|
||||
</div>
|
||||
<div style="padding: 1rem; border-top: var(--border-width) solid var(--light-border-color); display: flex; gap: 0.5rem;">
|
||||
<input type="text" id="chat-input" class="forminput" style="flex-grow: 1; margin: 0;" placeholder="{blah(placeholder.message.input)}">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue