forked from Ailur/burgernotes-server
fart
This commit is contained in:
parent
145cad27fa
commit
bcd6a07607
|
@ -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
12
main
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue