From f7920de8126aaff1052d0ddc41856992eb917440 Mon Sep 17 00:00:00 2001 From: maaa Date: Sun, 10 Mar 2024 23:00:40 +0100 Subject: [PATCH] "smart" titles --- APIDOCS.md | 15 ++++++----- main | 3 ++- static/js/main.js | 69 ++++++++++++++++++++++++++--------------------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/APIDOCS.md b/APIDOCS.md index c49dfbc..1d38020 100644 --- a/APIDOCS.md +++ b/APIDOCS.md @@ -1,9 +1,9 @@ -# Burgernotes API docs +# 🍔 Burgernotes API docs Use the Burgernotes API to automate tasks, build your own client, and more! Headers should be: "Content-type: application/json; charset=UTF-8" for all POSTs -## Authentication +## 🔑 Authentication POST - /api/signup - provide "username" and "password". @@ -46,13 +46,13 @@ You'll need to store two things in local storage: - The secret key you just got, used to fetch notes, save stuff etc. - A SHA512 hashed password, used as encryption key -## Encryption +## 🔐 Encryption Note content and title is encrypted using AES 256-bit. Encryption password is the SHA512 hashed password we talked about earlier. -## Basic stuff +## 🕹ī¸ Basic stuff POST - /api/userinfo - get user info such as username, provide "secretKey" @@ -65,15 +65,16 @@ POST - /api/newnote - create a note, provide "secretKey" and "noteName" POST - /api/readnote - read notes, provide "secretKey" and "noteId" note content will have to be decrypted. -POST - /api/editnote - edit notes, provide "secretKey", "noteId", and "content" +POST - /api/editnote - edit notes, provide "secretKey", "noteId", "title", and "content" "content" should be encrypted. +"title" is the first line of the note content, and should be encrypted. the title should be truncated if it's above 16 characters, meaning "sillyburgermuncher" -> "sillyburgermunch.." -POST - /api/editnotetitle - edit note titles, provide "secretKey", "noteId", and "content" +**(Deprecated ⚠ī¸)** POST - /api/editnotetitle - edit note titles, provide "secretKey", "noteId", and "content" "content" should be encrypted. POST - /api/removenote - remove notes, provide "secretKey" and "noteId" -## More stuff +## ⚙ī¸ More stuff POST - /api/deleteaccount - delete account, provide "secretKey" please display a warning before this action diff --git a/main b/main index 511e813..262d650 100644 --- a/main +++ b/main @@ -354,6 +354,7 @@ async def apieditnote(): secretKey = data["secretKey"] noteId = data["noteId"] content = data["content"] + title = data["title"] userCookie = get_session(secretKey) user = get_user(userCookie["id"]) @@ -366,7 +367,7 @@ async def apieditnote(): if (note != None): if (user["id"] == note["creator"]): conn = get_db_connection() - conn.execute("UPDATE notes SET content = ?, edited = ? WHERE id = ?", (content, str(time.time()), noteId)) + conn.execute("UPDATE notes SET content = ?, title = ?, edited = ? WHERE id = ?", (content, title, str(time.time()), noteId)) conn.commit() conn.close() diff --git a/static/js/main.js b/static/js/main.js index d0a4aa1..44795cc 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -359,6 +359,14 @@ function updateWordCount() { wordCountBox.innerText = wordCount + " words" } +function truncateString(str, num) { + if (str.length > num) { + return str.slice(0, num) + ".."; + } else { + return str; + } +} + function selectNote(nameithink) { document.querySelectorAll(".noteButton").forEach((el) => el.classList.remove("selected")); let thingArray = Array.from(document.querySelectorAll(".noteButton")).find(el => el.id == nameithink); @@ -399,6 +407,13 @@ function selectNote(nameithink) { updateWordCount() clearTimeout(timer); timer = setTimeout(() => { + let encryptedTitle = "empty note" + if (noteBox.value != "") { + let firstTitle = truncateString(noteBox.value.slice(0, noteBox.value.indexOf("\n")), 16) + + document.getElementById(nameithink).innerText = firstTitle + encryptedTitle = CryptoJS.AES.encrypt(firstTitle, password).toString(); + } let encryptedText = CryptoJS.AES.encrypt(noteBox.value, password).toString(); if (selectedNote == nameithink) { @@ -408,6 +423,7 @@ function selectNote(nameithink) { secretKey: secretkey, noteId: nameithink, content: encryptedText, + title: encryptedTitle }), headers: { "Content-Type": "application/json; charset=UTF-8" @@ -494,38 +510,29 @@ function updateNotes() { updateNotes() newNote.addEventListener("click", (event) => { - let noteName = displayPrompt("Note name?", "E.G Shopping list", burgerFunction) - function burgerFunction(noteName) { - if (noteName != null) { - if (noteName.length > 21) { - displayError("Invalid note name: Too long (max 21 characters)"); - return; - } - - let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(); - fetch(remote + "/api/newnote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteName: encryptedName, - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .catch((error) => { - displayError("Failed to create new note, please try again later...") - }) - .then((response) => { - if (response.status !== 200) { - updateNotes() - displayError("Failed to create new note (HTTP error code " + response.status + ")") - } else { - updateNotes() - } - }); + let noteName = "empty note" + let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(); + fetch(remote + "/api/newnote", { + method: "POST", + body: JSON.stringify({ + secretKey: secretkey, + noteName: encryptedName, + }), + headers: { + "Content-Type": "application/json; charset=UTF-8" } - } + }) + .catch((error) => { + displayError("Failed to create new note, please try again later...") + }) + .then((response) => { + if (response.status !== 200) { + updateNotes() + displayError("Failed to create new note (HTTP error code " + response.status + ")") + } else { + updateNotes() + } + }); }); function downloadObjectAsJson(exportObj, exportName) { var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));