From 70d3a32ae766dc15fd6c21e382068f44dbaff8b8 Mon Sep 17 00:00:00 2001 From: Alexis Hovorka Date: Tue, 13 Feb 2024 23:11:36 -0700 Subject: [feat] Flesh out auth flow and note store --- app/public/index.html | 21 +++++- app/public/main.js | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) (limited to 'app/public') diff --git a/app/public/index.html b/app/public/index.html index 3c435f5..d5932a1 100644 --- a/app/public/index.html +++ b/app/public/index.html @@ -52,12 +52,31 @@ - +

Notes

+
+ + + + +
+
+ + +
+ + +
+ + + +
+ + diff --git a/app/public/main.js b/app/public/main.js index ff960c2..5dc9531 100644 --- a/app/public/main.js +++ b/app/public/main.js @@ -5,6 +5,17 @@ const $ = (s,c) => (c||document).querySelector(s); function $$(x,y,z,a){a=(z||document).querySelectorAll(x);if(typeof y=="function")[].forEach.call(a,y);return a} function m(a,b,c){c=document;b=c.createElement(b||"p");b.innerHTML=a.trim();for(a=c.createDocumentFragment();c=b.firstChild;)a.appendChild(c);return a.firstChild} +function debounce(fn, delay) { + let timeout = null; + return (...args) => { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(() => { + timeout = null; + fn.apply(null, args); + }, delay||500); + } +} + //sock.init(`ws${secure?"s":""}://${location.host}/ws`); //sock.on("hello", e => { // console.log("hello", e); @@ -15,4 +26,168 @@ function m(a,b,c){c=document;b=c.createElement(b||"p");b.innerHTML=a.trim();for( // navigator.serviceWorker.register("sw.js") // .then(() => console.log("Service worker registered")); //} + +function drawNote(note) { + const el = m(`
+

${note.id}

+ +
`); + + $("textarea", el).addEventListener("input", + debounce(() => { saveNote(note.id, $("textarea", el).value); }, 500)); + + $("#notes").appendChild(el); +} + +async function getNote(id) { + const res = await fetch(`${id}`); + const note = await res.json(); + console.log(note); + drawNote(note); +} + +async function getList() { + const res = await fetch("/list"); + const list = await res.json(); + console.log(list); + + for (let i=0;i { + const res = await fetch("/login", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ + username: $("#username").value, + password: $("#password").value, + keepSession: $("#keep-session").checked, + }) + }); + + // TODO check return code + + const json = await res.json(); + console.log(json); + + // TODO "Must Change Password" flow + + getUserData(); + getList(); +}); + +$("#change-password").addEventListener("click", async () => { + const res = await fetch("/change-password", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ + username: $("#username").value, + password: $("#password").value, + newPassword: $("#new-password").value, + keepSession: $("#keep-session").checked, + }) + }); + + const json = await res.json(); + console.log(json); + + getUserData(); +}); + +$("#change-username").addEventListener("click", async () => { + const res = await fetch("/change-username", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ + newUsername: $("#new-username").value, + password: $("#password").value, + }) + }); + + const json = await res.json(); + console.log(json); + + getUserData(); +}); + +$("#logout").addEventListener("click", async () => { + const res = await fetch("/logout", { + method: "POST", + }); + + //const json = await res.json(); + //console.log(json); + console.log("Logged out"); + $("#uid").value = ""; +}); + +$("#logout-everywhere").addEventListener("click", async () => { + const res = await fetch("/deauth-all", { + method: "POST", + }); + + console.log("Logged out everywhere"); + $("#uid").value = ""; +}); + +try { getUserData(); getList(); getUserSessions(); } catch(e) {} + +// TODO make sure to save unsynced delta even if token has expired, then sync when logged in +// TODO Cookie consent on signup; "only necessary for maintaining user session and cached data" +// TODO "Review sessions" popup client-side when relogin required on a token which shouldn't have expired yet + +// TODO prevent data: and javascript: links? +// Also embedding of external content? +// encodeURI *AND* encode for attribute (quote marks etc) +// https://github.com/cure53/DOMPurify +// +// elem.textContent = dangerVariable; !!!!!!!!! +// elem.insertAdjacentText(dangerVariable); +// elem.className = dangerVariable; +// elem.setAttribute(safeName, dangerVariable); +// formfield.value = dangerVariable; +// document.createTextNode(dangerVariable); +// document.createElement(dangerVariable); +// elem.innerHTML = DOMPurify.sanitize(dangerVar); +// https://github.com/cure53/DOMPurify/blob/main/src/attrs.js +// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + }); -- cgit v1.2.3-70-g09d2