initial 2FA support

This commit is contained in:
MathMan05 2024-08-09 18:54:34 -05:00
parent c27a9af9bd
commit 13c896d756
6 changed files with 262 additions and 11 deletions

View file

@ -34,6 +34,7 @@ class Localuser {
wsinterval;
connectionSucceed = 0;
errorBackoff = 0;
mfa_enabled;
constructor(userinfo) {
this.token = userinfo.token;
this.userinfo = userinfo;
@ -49,6 +50,7 @@ class Localuser {
this.guilds = [];
this.guildids = new Map();
this.user = new User(ready.d.user, this);
this.mfa_enabled = ready.d.user.mfa_enabled;
this.userinfo.username = this.user.username;
this.userinfo.pfpsrc = this.user.getpfpsrc();
this.status = this.ready.d.user_settings.status;
@ -718,6 +720,67 @@ class Localuser {
}, { initColor: userinfos.accent_color });
}
}
{
const security = settings.addButton("Account Security");
if (this.mfa_enabled) {
security.addTextInput("Disable 2FA, totp code:", _ => {
fetch(this.info.api.toString() + "/users/@me/mfa/totp/disable", {
method: "POST",
headers: this.headers,
body: JSON.stringify({
code: _
})
}).then(r => r.json()).then(json => {
if (json.message) {
alert(json.message);
}
else {
this.mfa_enabled = false;
alert("2FA turned off successfully");
}
});
});
}
else {
security.addButtonInput("", "Enable 2FA", async () => {
let secret = "";
for (let i = 0; i < 18; i++) {
secret += "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[Math.floor(Math.random() * 32)];
}
let password = "";
let code = "";
const addmodel = new Fullscreen(["vdiv",
["title", "2FA set up"],
["text", "Copy this secret into your totp(time-based one time password) app"],
["text", `Your secret is: ${secret} and it's 6 digits, with a 30 second token period`],
["textbox", "Account password:", "", function () { password = this.value; }],
["textbox", "Code:", "", function () { code = this.value; }],
["button", "", "Submit", () => {
fetch(this.info.api.toString() + "/users/@me/mfa/totp/enable/", {
method: "POST",
headers: this.headers,
body: JSON.stringify({
password,
code,
secret
})
}).then(r => r.json()).then(json => {
if (json.message) {
alert(json.message);
}
else {
alert("2FA set up successfully");
addmodel.hide();
this.mfa_enabled = true;
}
});
}]
]);
console.log("here :3");
addmodel.show();
});
}
}
settings.show();
}
/**

View file

@ -1,3 +1,4 @@
import { Fullscreen } from "/fullscreen.js";
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
export { mobile, getBulkUsers, getBulkInfo, setTheme, Specialuser };
function setTheme() {
@ -167,8 +168,8 @@ async function login(username, password, captcha) {
};
try {
const info = JSON.parse(localStorage.getItem("instanceinfo"));
const url = new URL(info.login);
return await fetch(url.origin + '/api/auth/login', options).then(response => response.json())
const api = info.login;
return await fetch(api + '/auth/login', options).then(response => response.json())
.then((response) => {
console.log(response, response.message);
if ("Invalid Form Body" === response.message) {
@ -194,9 +195,35 @@ async function login(username, password, captcha) {
return;
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
return response.token;
console.log(response);
if (response.ticket) {
let onetimecode = "";
new Fullscreen(["vdiv", ["title", "2FA code:"], ["textbox", "", "", function () { onetimecode = this.value; }], ["button", "", "Submit", function () {
fetch(api + "/auth/mfa/totp", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
code: onetimecode,
ticket: response.ticket,
})
}).then(r => r.json()).then(response => {
if (response.message) {
alert(response.message);
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
}
});
}]]).show();
}
else {
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
return response.token;
}
}
});
}

View file

@ -1,6 +1,7 @@
import { Permissions } from "./permissions.js";
import { SnowFlake } from "./snowflake.js";
import { Role } from "./role.js";
//future me stuff
class Buttons {
name;
buttons;
@ -175,6 +176,35 @@ class TextInput {
this.onSubmit(this.textContent);
}
}
class ButtonInput {
label;
owner;
onClick;
textContent;
constructor(label, textContent, onClick, owner, {} = {}) {
this.label = label;
this.owner = owner;
this.onClick = onClick;
this.textContent = textContent;
}
generateHTML() {
const div = document.createElement("div");
const span = document.createElement("span");
span.textContent = this.label;
div.append(span);
const button = document.createElement("button");
button.textContent = this.textContent;
button.onclick = this.onClickEvent.bind(this);
div.append(button);
return div;
}
onClickEvent(ev) {
console.log("here :3");
this.onClick();
}
watchForChange() { }
submit() { }
}
class ColorInput {
label;
owner;
@ -443,6 +473,11 @@ class Options {
this.options.push(htmlarea);
return htmlarea;
}
addButtonInput(label, textContent, onSubmit) {
const button = new ButtonInput(label, textContent, onSubmit, this);
this.options.push(button);
return button;
}
generateHTML() {
const div = document.createElement("div");
div.classList.add("titlediv");