From dbe323c77e6981db59b79f23b97fdf6974749121 Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Wed, 10 Dec 2025 16:50:31 +0100 Subject: [PATCH] almost done --- frontend/src/pages/profile/profile.html | 53 ++- frontend/src/pages/profile/profile.ts | 428 ++++++++++++------------ 2 files changed, 232 insertions(+), 249 deletions(-) diff --git a/frontend/src/pages/profile/profile.html b/frontend/src/pages/profile/profile.html index 6752e23..76c7565 100644 --- a/frontend/src/pages/profile/profile.html +++ b/frontend/src/pages/profile/profile.html @@ -1,18 +1,14 @@

Edit Profile

- -
- - + + Unknown
- - @@ -39,54 +36,42 @@ - +
- - -
+ - -
+ -
diff --git a/frontend/src/pages/profile/profile.ts b/frontend/src/pages/profile/profile.ts index 39171ce..4b91b84 100644 --- a/frontend/src/pages/profile/profile.ts +++ b/frontend/src/pages/profile/profile.ts @@ -6,15 +6,7 @@ import { isNullish } from "@app/utils"; import client from "@app/api"; import QRCode from "qrcode"; -type OAuthQRCodeOptions = { - label?: string; // e.g. your-app:user@example.com - issuer?: string; // e.g. "YourApp" - algorithm?: "SHA1" | "SHA256" | "SHA512"; - digits?: number; - period?: number; -}; - -/** +/* * Renders an OAuth2-compatible TOTP QR code into a canvas. * * @param canvas HTMLCanvasElement to draw into @@ -38,219 +30,225 @@ export async function renderOAuth2QRCode( }); canvas.style.width = ""; canvas.style.height = ""; - function removeBgColor(...elem: HTMLElement[]) { - for (let e of elem) { - for (let c of e.classList.values()) { - if (c.startsWith("bg-") || c.startsWith("hover:bg-")) - e.classList.remove(c); - } +} +function removeBgColor(...elem: HTMLElement[]) { + for (let e of elem) { + for (let c of e.classList.values()) { + if (c.startsWith("bg-") || c.startsWith("hover:bg-")) + e.classList.remove(c); } } +} - async function route(url: string, _args: { [k: string]: string }) { - setTitle("Edit Profile"); - return { - html: page, - postInsert: async (app: HTMLElement | undefined) => { - const user = await updateUser(); - if (isNullish(user)) return showError("No User"); - if (isNullish(app)) return showError("Failed to render"); - let totpState = await (async () => { - let res = await client.statusOtp(); - if (res.kind === "success") - return { - enabled: - (res.msg as string) === "statusOtp.success.enabled", - secret: - (res.msg as string) === "statusOtp.success.enabled" - ? res.payload.secret - : null, - }; - else { - showError("Failed to get OTP status"); - return { - enabled: false, - secret: null, - }; - } - })(); - // ---- Simulated State ---- - let totpEnabled = totpState.enabled; - let totpSecret = totpState.secret; // would come from backend - - let guestBox = app.querySelector("#isGuestBox")!; - let displayNameWrapper = app.querySelector( - "#displayNameWrapper", - )!; - let displayNameBox = - app.querySelector("#displayNameBox")!; - let displayNameButton = - app.querySelector("#displayNameButton")!; - let loginNameWrapper = - app.querySelector("#loginNameWrapper")!; - let loginNameBox = - app.querySelector("#loginNameBox")!; - let passwordWrapper = - app.querySelector("#passwordWrapper")!; - let passwordBox = - app.querySelector("#passwordBox")!; - let passwordButton = - app.querySelector("#passwordButton")!; - - let providerWrapper = - app.querySelector("#providerWrapper")!; - let providerNameBox = - app.querySelector("#providerNameBox")!; - let providerUserBox = - app.querySelector("#providerUserBox")!; - - let accountTypeBox = - app.querySelector("#accountType")!; - displayNameBox.value = user.name; - - guestBox.hidden = !user.guest; - - // ---- DOM Elements ---- - const totpStatusText = app.querySelector("#totpStatusText")!; - const enableBtn = - app.querySelector("#enableTotp")!; - const disableBtn = - app.querySelector("#disableTotp")!; - const showSecretBtn = - app.querySelector("#showSecret")!; - const secretBox = app.querySelector("#totpSecretBox")!; - const secretText = - app.querySelector("#totpSecretText")!; - const secretCanvas = - app.querySelector("#totpSecretCanvas")!; - - if (user.guest) { - for (let c of passwordButton.classList.values()) { - if (c.startsWith("bg-") || c.startsWith("hover:bg-")) - passwordButton.classList.remove(c); - } - let totpWrapper = app.querySelector("#totpWrapper")!; - - if (user.guest) { - removeBgColor( - passwordButton, - displayNameButton, - enableBtn, - disableBtn, - showSecretBtn, - ); - - passwordButton.classList.add( - "bg-gray-700", - "hover:bg-gray-700", - ); - - passwordBox.disabled = true; - passwordBox.classList.add("color-white"); - - displayNameButton.disabled = true; - displayNameButton.classList.add("bg-gray-700", "color-white"); - - displayNameBox.disabled = true; - displayNameBox.classList.add("color-white"); - enableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - disableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - showSecretBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - - enableBtn.disabled = true; - disableBtn.disabled = true; - showSecretBtn.disabled = true; - - accountTypeBox.innerText = "Guest"; - } else if (!isNullish(user.selfInfo?.loginName)) { - loginNameWrapper.hidden = false; - loginNameBox.innerText = user.selfInfo.loginName; - - accountTypeBox.innerText = "Normal"; - } else if ( - !isNullish(user.selfInfo?.providerId) && - !isNullish(user.selfInfo?.providerUser) - ) { - providerWrapper.hidden = false; - providerNameBox.innerText = user.selfInfo.providerId; - providerUserBox.innerText = user.selfInfo.providerUser; - - enableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - disableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - showSecretBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); - - enableBtn.disabled = true; - disableBtn.disabled = true; - showSecretBtn.disabled = true; - - removeBgColor(enableBtn, disableBtn, showSecretBtn); - passwordWrapper.hidden = true; - totpWrapper.hidden = true; - - accountTypeBox.innerText = "Provider"; - } - - // ---- Update UI ---- - function refreshTotpUI() { - if (totpEnabled) { - totpStatusText.textContent = "Status: Enabled"; - - enableBtn.classList.add("hidden"); - disableBtn.classList.remove("hidden"); - showSecretBtn.classList.remove("hidden"); - } else { - totpStatusText.textContent = "Status: Disabled"; - - enableBtn.classList.remove("hidden"); - disableBtn.classList.add("hidden"); - showSecretBtn.classList.add("hidden"); - secretBox.classList.add("hidden"); - } - } - - // ---- Button Events ---- - enableBtn.onclick = async () => { - let res = await client.enableOtp(); - if (res.kind === "success") { - navigateTo(url); - } else { - showError(`failed to activate OTP: ${res.msg}`); - } +async function route(url: string, _args: { [k: string]: string }) { + setTitle("Edit Profile"); + return { + html: page, + postInsert: async (app: HTMLElement | undefined) => { + const user = await updateUser(); + if (isNullish(user)) return showError("No User"); + if (isNullish(app)) return showError("Failed to render"); + let totpState = await (async () => { + let res = await client.statusOtp(); + if (res.kind === "success") + return { + enabled: + (res.msg as string) === "statusOtp.success.enabled", + secret: + (res.msg as string) === "statusOtp.success.enabled" + ? res.payload.secret + : null, }; - - disableBtn.onclick = async () => { - let res = await client.disableOtp(); - if (res.kind === "success") { - navigateTo(url); - } else { - showError(`failed to deactivate OTP: ${res.msg}`); - } + else { + showError("Failed to get OTP status"); + return { + enabled: false, + secret: null, }; + } + })(); + // ---- Simulated State ---- + let totpEnabled = totpState.enabled; + let totpSecret = totpState.secret; // would come from backend - showSecretBtn.onclick = () => { - if (!isNullish(totpSecret)) { - secretText.textContent = totpSecret; - renderOAuth2QRCode(secretCanvas, totpSecret); - } - secretBox.classList.toggle("hidden"); - }; + let guestBox = app.querySelector("#isGuestBox")!; + let displayNameWrapper = app.querySelector( + "#displayNameWrapper", + )!; + let displayNameBox = + app.querySelector("#displayNameBox")!; + let displayNameButton = + app.querySelector("#displayNameButton")!; + let loginNameWrapper = + app.querySelector("#loginNameWrapper")!; + let loginNameBox = + app.querySelector("#loginNameBox")!; + let passwordWrapper = + app.querySelector("#passwordWrapper")!; + let passwordBox = + app.querySelector("#passwordBox")!; + let passwordButton = + app.querySelector("#passwordButton")!; - displayNameButton.onclick = async () => { - let req = await client.changeDisplayName({ - changeDisplayNameRequest: { name: displayNameBox.value }, - }); - if (req.kind === "success") { - showSuccess("Successfully changed display name"); - handleRoute(); - } else { - showError(`Failed to update: ${req.msg}`); - } - }; + let providerWrapper = + app.querySelector("#providerWrapper")!; + let providerNameBox = + app.querySelector("#providerNameBox")!; + let providerUserBox = + app.querySelector("#providerUserBox")!; - // Initialize UI state - refreshTotpUI(); - }, + let accountTypeBox = + app.querySelector("#accountType")!; + displayNameBox.value = user.name; + + guestBox.hidden = !user.guest; + + // ---- DOM Elements ---- + const totpStatusText = app.querySelector("#totpStatusText")!; + const enableBtn = + app.querySelector("#enableTotp")!; + const disableBtn = + app.querySelector("#disableTotp")!; + const showSecretBtn = + app.querySelector("#showSecret")!; + const secretBox = app.querySelector("#totpSecretBox")!; + const secretText = + app.querySelector("#totpSecretText")!; + const secretCanvas = + app.querySelector("#totpSecretCanvas")!; + let totpWrapper = + app.querySelector("#totpWrapper")!; + + if (user.guest) { + for (let c of passwordButton.classList.values()) { + if (c.startsWith("bg-") || c.startsWith("hover:bg-")) + passwordButton.classList.remove(c); + } + } + if (user.guest) { + removeBgColor( + passwordButton, + displayNameButton, + enableBtn, + disableBtn, + showSecretBtn, + ); + + passwordButton.classList.add( + "bg-gray-700", + "hover:bg-gray-700", + ); + + passwordBox.disabled = true; + passwordBox.classList.add("color-white"); + + displayNameButton.disabled = true; + displayNameButton.classList.add("bg-gray-700", "color-white"); + + displayNameBox.disabled = true; + displayNameBox.classList.add("color-white"); + enableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + disableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + showSecretBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + + enableBtn.disabled = true; + disableBtn.disabled = true; + showSecretBtn.disabled = true; + + accountTypeBox.innerText = "Guest"; + } else if (!isNullish(user.selfInfo?.loginName)) { + loginNameWrapper.hidden = false; + loginNameBox.innerText = user.selfInfo.loginName; + totpWrapper.hidden =false; + passwordWrapper.hidden = false; + + accountTypeBox.innerText = "Normal"; + } else if ( + !isNullish(user.selfInfo?.providerId) && + !isNullish(user.selfInfo?.providerUser) + ) { + providerWrapper.hidden = false; + providerNameBox.innerText = user.selfInfo.providerId; + providerUserBox.innerText = user.selfInfo.providerUser; + + enableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + disableBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + showSecretBtn.classList.add("bg-gray-700", "hover:bg-gray-700"); + + enableBtn.disabled = true; + disableBtn.disabled = true; + showSecretBtn.disabled = true; + + removeBgColor(enableBtn, disableBtn, showSecretBtn); + passwordWrapper.hidden = true; + totpWrapper.hidden = true; + + accountTypeBox.innerText = "Provider"; + } + + // ---- Update UI ---- + function refreshTotpUI() { + if (totpEnabled) { + totpStatusText.textContent = "Status: Enabled"; + + enableBtn.classList.add("hidden"); + disableBtn.classList.remove("hidden"); + showSecretBtn.classList.remove("hidden"); + } else { + totpStatusText.textContent = "Status: Disabled"; + + enableBtn.classList.remove("hidden"); + disableBtn.classList.add("hidden"); + showSecretBtn.classList.add("hidden"); + secretBox.classList.add("hidden"); + } + } + + // ---- Button Events ---- + enableBtn.onclick = async () => { + let res = await client.enableOtp(); + if (res.kind === "success") { + navigateTo(url); + } else { + showError(`failed to activate OTP: ${res.msg}`); + } }; - } - addRoute("/profile", route); + disableBtn.onclick = async () => { + let res = await client.disableOtp(); + if (res.kind === "success") { + navigateTo(url); + } else { + showError(`failed to deactivate OTP: ${res.msg}`); + } + }; + + showSecretBtn.onclick = () => { + if (!isNullish(totpSecret)) { + secretText.textContent = totpSecret; + renderOAuth2QRCode(secretCanvas, totpSecret); + } + secretBox.classList.toggle("hidden"); + }; + + displayNameButton.onclick = async () => { + let req = await client.changeDisplayName({ + changeDisplayNameRequest: { + name: displayNameBox.value, + }, + }); + if (req.kind === "success") { + showSuccess("Successfully changed display name"); + handleRoute(); + } else { + showError(`Failed to update: ${req.msg}`); + } + }; + + // Initialize UI state + refreshTotpUI(); + }, + }; +} + +addRoute("/profile", route);