This commit is contained in:
maaa 2023-08-06 00:28:57 +02:00
parent 145cad27fa
commit bcd6a07607
3 changed files with 71 additions and 3 deletions

53
APIDOCS.md Normal file
View File

@ -0,0 +1,53 @@
# Burgernotes API docs
Use the Burgernotes API to automate tasks, build your own client, and more!
## Authentication
POST - /api/signup - provide "username" and "password".
POST - /api/login - provide "username" and "password".
To prevent the server from knowing the encryption key, password you provide in the request must be hashed with the argon2 algorithm.
The salt should be the password.
Password must be at least 14 characters, username must be under 20 characters and alphanumeric.
If username is taken, error code 422 will return.
Assuming everything went correctly, the server will return a secret key.
You'll need to store two things in local storage:
- The secret key you just got, used to fetch notes, save stuff etc.
- SHA512 hashed password, used as encryption key
## Encryption
Note content and title is encrypted using AES 256-bit.
Encryption password is the SHA512 hashed password we talked about earlier.
## Basic stuff
POST - /api/userinfo - get user info such as username, provide "secretKey"
POST - /api/listnotes - list notes, provide "secretKey"
note titles will have to be decrypted.
POST - /api/newnote - create a note, provide "secretKey" and "noteName"
"noteName" should be encrypted.
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"
"content" should be encrypted.
POST - /api/removenote - remove notes, provide "secretKey" and "noteId"
## More stuff
POST - /api/deleteaccount - delete account, provide "secretKey"
please display a warning before this action
POST - /api/exportnotes - export notes, provide "secretKey"
note content and title will have to be decrypted

12
main
View File

@ -58,6 +58,15 @@ def get_space(id):
spacetaken = spacetaken + len(x["title"].encode("utf-8")) spacetaken = spacetaken + len(x["title"].encode("utf-8"))
return spacetaken return spacetaken
def get_note_count(id):
conn = get_db_connection()
notes = conn.execute("SELECT content, title FROM notes WHERE creator = ? ORDER BY id DESC;", (id,)).fetchall()
conn.close()
notecount = 0
for x in notes:
notecount = notecount + 1
return notecount
def get_session(id): def get_session(id):
conn = get_db_connection() conn = get_db_connection()
post = conn.execute("SELECT * FROM sessions WHERE session = ?", post = conn.execute("SELECT * FROM sessions WHERE session = ?",
@ -187,7 +196,8 @@ def apiuserinfo():
"id": user["id"], "id": user["id"],
"created": user["created"], "created": user["created"],
"storageused": get_space(user["id"]), "storageused": get_space(user["id"]),
"storagemax": MAX_STORAGE "storagemax": MAX_STORAGE,
"notecount": get_note_count(user["id"])
} }
return datatemplate return datatemplate

View File

@ -90,6 +90,8 @@ if (/Android|iPhone/i.test(navigator.userAgent)) {
noteBox.value = "" noteBox.value = ""
noteBox.readOnly = true noteBox.readOnly = true
let noteCount = 0
function updateUserInfo() { function updateUserInfo() {
fetch("/api/userinfo", { fetch("/api/userinfo", {
method: "POST", method: "POST",
@ -109,6 +111,7 @@ function updateUserInfo() {
storageThing.innerText = "you've used " + formatBytes(responseData["storageused"]) + " out of " + formatBytes(responseData["storagemax"]) storageThing.innerText = "you've used " + formatBytes(responseData["storageused"]) + " out of " + formatBytes(responseData["storagemax"])
storageProgressThing.value = responseData["storageused"] storageProgressThing.value = responseData["storageused"]
storageProgressThing.max = responseData["storagemax"] storageProgressThing.max = responseData["storagemax"]
noteCount = responseData["notecount"]
} }
doStuff() doStuff()
}); });
@ -333,6 +336,8 @@ function exportNotes() {
async function doStuff() { async function doStuff() {
let responseData = await response.json() let responseData = await response.json()
for (let i in responseData) { for (let i in responseData) {
exportNotes.innerText = "decrypting " + i + "/" + noteCount
let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password); let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password);
let originalTitle = bytes.toString(CryptoJS.enc.Utf8); let originalTitle = bytes.toString(CryptoJS.enc.Utf8);
@ -346,6 +351,7 @@ function exportNotes() {
let jsonString = JSON.parse(JSON.stringify(responseData)) let jsonString = JSON.parse(JSON.stringify(responseData))
console.log(jsonString) console.log(jsonString)
exportNotesButton.innerText = "export notes"
downloadObjectAsJson(jsonString, "data") downloadObjectAsJson(jsonString, "data")
} }
doStuff() doStuff()
@ -353,7 +359,6 @@ function exportNotes() {
} }
exportNotesButton.addEventListener("click", (event) => { exportNotesButton.addEventListener("click", (event) => {
exportNotesButton.innerText = "exporting.." exportNotesButton.innerText = "downloading.."
exportNotes() exportNotes()
exportNotesButton.innerText = "export notes"
}); });