Merge branch 'main' of ssh://hectabit.org/HectaBit/PageBurger
This commit is contained in:
commit
7f665f57a9
|
@ -1,9 +1,11 @@
|
||||||
## PageBurger
|
## PageBurger
|
||||||
PageBurger is a simple note-taking app with end-to-end encryption.
|
PageBurger is a simple note-taking app with end-to-end encryption.
|
||||||
|
|
||||||
PageBurger is a community fork of the discontinued [BurgerNotes](https://codeberg.org/burger-software/burgernotes). Most of the credits go to BurgerSoftware.
|
PageBurger is a community fork of the discontinued [burgernotes](https://codeberg.org/burger-software/burgernotes). Most of the credits go to burger software.
|
||||||
|
|
||||||
### links
|
### Links
|
||||||
[Go to the PageBurger website](https://notes.hectabit.org)
|
[Go to the PageBurger website](https://notes.hectabit.org)
|
||||||
|
|
||||||
[API documentation](APIDOCS.md)
|
[API documentation](APIDOCS.md)
|
||||||
|
|
||||||
|
[Roadmap](ROADMAP.md)
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Pageburger Roadmap
|
||||||
|
|
||||||
|
- Switch to WebSockets for updating notes + live updating of note list and more, this involves redoing some APIs
|
||||||
|
- Compress notes to reduce bandwidth and storage
|
||||||
|
- Dedicated domain (not just a subdomain, if anyone can donate a domain let Arzumify know!)
|
||||||
|
- Native Apps (native iOS and Linux apps are in development)
|
95
main
95
main
|
@ -4,9 +4,11 @@ import sqlite3
|
||||||
import time
|
import time
|
||||||
import secrets
|
import secrets
|
||||||
import configparser
|
import configparser
|
||||||
from waitress import serve
|
import asyncio
|
||||||
|
from hypercorn.config import Config
|
||||||
|
from hypercorn.asyncio import serve
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
from flask import Flask, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request
|
from quart import Quart, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request
|
||||||
|
|
||||||
# Parse configuration file, and check if anything is wrong with it
|
# Parse configuration file, and check if anything is wrong with it
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
@ -20,8 +22,8 @@ MAX_STORAGE = config["config"]["MAX_STORAGE"]
|
||||||
if SECRET_KEY == "placeholder":
|
if SECRET_KEY == "placeholder":
|
||||||
print("[WARNING] Secret key not set")
|
print("[WARNING] Secret key not set")
|
||||||
|
|
||||||
# Define Flask
|
# Define Quart
|
||||||
app = Flask(__name__)
|
app = Quart(__name__)
|
||||||
app.config["SECRET_KEY"] = SECRET_KEY
|
app.config["SECRET_KEY"] = SECRET_KEY
|
||||||
|
|
||||||
# Database functions
|
# Database functions
|
||||||
|
@ -96,37 +98,37 @@ def check_username_taken(username):
|
||||||
|
|
||||||
# Main page
|
# Main page
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def main():
|
async def main():
|
||||||
return render_template("main.html")
|
return await render_template("main.html")
|
||||||
|
|
||||||
# Web app
|
# Web app
|
||||||
@app.route("/app")
|
@app.route("/app")
|
||||||
def webapp():
|
async def webapp():
|
||||||
return render_template("app.html")
|
return await render_template("app.html")
|
||||||
|
|
||||||
# Login and signup
|
# Login and signup
|
||||||
@app.route("/signup")
|
@app.route("/signup")
|
||||||
def signup():
|
async def signup():
|
||||||
return render_template("signup.html")
|
return await render_template("signup.html")
|
||||||
|
|
||||||
@app.route("/login")
|
@app.route("/login")
|
||||||
def login():
|
async def login():
|
||||||
return render_template("login.html")
|
return await render_template("login.html")
|
||||||
|
|
||||||
# Privacy policy
|
# Privacy policy
|
||||||
@app.route("/privacy")
|
@app.route("/privacy")
|
||||||
def privacy():
|
async def privacy():
|
||||||
return render_template("privacy.html")
|
return await render_template("privacy.html")
|
||||||
|
|
||||||
# API
|
# API
|
||||||
@app.route("/api/version", methods=("GET", "POST"))
|
@app.route("/api/version", methods=("GET", "POST"))
|
||||||
def apiversion():
|
async def apiversion():
|
||||||
return "PageBurger Version 1.1"
|
return "PageBurger Version 1.1"
|
||||||
|
|
||||||
@app.route("/api/signup", methods=("GET", "POST"))
|
@app.route("/api/signup", methods=("GET", "POST"))
|
||||||
def apisignup():
|
async def apisignup():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
username = data["username"]
|
username = data["username"]
|
||||||
password = data["password"]
|
password = data["password"]
|
||||||
|
|
||||||
|
@ -172,9 +174,9 @@ def apisignup():
|
||||||
}, 200
|
}, 200
|
||||||
|
|
||||||
@app.route("/api/login", methods=("GET", "POST"))
|
@app.route("/api/login", methods=("GET", "POST"))
|
||||||
def apilogin():
|
async def apilogin():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
username = data["username"]
|
username = data["username"]
|
||||||
password = data["password"]
|
password = data["password"]
|
||||||
|
|
||||||
|
@ -227,9 +229,9 @@ def apilogin():
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
@app.route("/api/userinfo", methods=("GET", "POST"))
|
@app.route("/api/userinfo", methods=("GET", "POST"))
|
||||||
def apiuserinfo():
|
async def apiuserinfo():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
|
@ -245,9 +247,9 @@ def apiuserinfo():
|
||||||
return datatemplate
|
return datatemplate
|
||||||
|
|
||||||
@app.route("/api/listnotes", methods=("GET", "POST"))
|
@app.route("/api/listnotes", methods=("GET", "POST"))
|
||||||
def apilistnotes():
|
async def apilistnotes():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
|
@ -269,9 +271,9 @@ def apilistnotes():
|
||||||
return datatemplate, 200
|
return datatemplate, 200
|
||||||
|
|
||||||
@app.route("/api/exportnotes", methods=("GET", "POST"))
|
@app.route("/api/exportnotes", methods=("GET", "POST"))
|
||||||
def apiexportnotes():
|
async def apiexportnotes():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
|
@ -296,9 +298,9 @@ def apiexportnotes():
|
||||||
return datatemplate, 200
|
return datatemplate, 200
|
||||||
|
|
||||||
@app.route("/api/newnote", methods=("GET", "POST"))
|
@app.route("/api/newnote", methods=("GET", "POST"))
|
||||||
def apinewnote():
|
async def apinewnote():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
noteName = data["noteName"]
|
noteName = data["noteName"]
|
||||||
|
|
||||||
|
@ -314,9 +316,9 @@ def apinewnote():
|
||||||
return {}, 200
|
return {}, 200
|
||||||
|
|
||||||
@app.route("/api/readnote", methods=("GET", "POST"))
|
@app.route("/api/readnote", methods=("GET", "POST"))
|
||||||
def apireadnote():
|
async def apireadnote():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
noteId = data["noteId"]
|
noteId = data["noteId"]
|
||||||
|
|
||||||
|
@ -338,9 +340,9 @@ def apireadnote():
|
||||||
return {}, 422
|
return {}, 422
|
||||||
|
|
||||||
@app.route("/api/editnote", methods=("GET", "POST"))
|
@app.route("/api/editnote", methods=("GET", "POST"))
|
||||||
def apieditnote():
|
async def apieditnote():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
noteId = data["noteId"]
|
noteId = data["noteId"]
|
||||||
content = data["content"]
|
content = data["content"]
|
||||||
|
@ -367,9 +369,9 @@ def apieditnote():
|
||||||
return {}, 422
|
return {}, 422
|
||||||
|
|
||||||
@app.route("/api/removenote", methods=("GET", "POST"))
|
@app.route("/api/removenote", methods=("GET", "POST"))
|
||||||
def apiremovenote():
|
async def apiremovenote():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
noteId = data["noteId"]
|
noteId = data["noteId"]
|
||||||
|
|
||||||
|
@ -393,9 +395,9 @@ def apiremovenote():
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/deleteaccount", methods=("GET", "POST"))
|
@app.route("/api/deleteaccount", methods=("GET", "POST"))
|
||||||
def apideleteaccount():
|
async def apideleteaccount():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
|
@ -414,9 +416,9 @@ def apideleteaccount():
|
||||||
return {}, 200
|
return {}, 200
|
||||||
|
|
||||||
@app.route("/api/sessions/list", methods=("GET", "POST"))
|
@app.route("/api/sessions/list", methods=("GET", "POST"))
|
||||||
def apisessionslist():
|
async def apisessionslist():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
|
@ -443,9 +445,9 @@ def apisessionslist():
|
||||||
return datatemplate, 200
|
return datatemplate, 200
|
||||||
|
|
||||||
@app.route("/api/sessions/remove", methods=("GET", "POST"))
|
@app.route("/api/sessions/remove", methods=("GET", "POST"))
|
||||||
def apisessionsremove():
|
async def apisessionsremove():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
sessionId = data["sessionId"]
|
sessionId = data["sessionId"]
|
||||||
|
|
||||||
|
@ -483,19 +485,22 @@ def listusers(secretkey):
|
||||||
return redirect("/")
|
return redirect("/")
|
||||||
|
|
||||||
@app.route("/api/logout")
|
@app.route("/api/logout")
|
||||||
def apilogout():
|
async def apilogout():
|
||||||
return render_template("logout.html")
|
return await render_template("logout.html")
|
||||||
|
|
||||||
@app.errorhandler(500)
|
@app.errorhandler(500)
|
||||||
def burger(e):
|
async def burger(e):
|
||||||
return {}, 500
|
return {}, 500
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def burger(e):
|
async def burger(e):
|
||||||
return render_template("error.html", errorCode=404, errorMessage="Page not found"), 404
|
return await render_template("error.html", errorCode=404, errorMessage="Page not found"), 404
|
||||||
|
|
||||||
# Start server
|
# Start server
|
||||||
|
hypercornconfig = Config()
|
||||||
|
hypercornconfig.bind = (HOST + ":" + PORT)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("[INFO] Server started")
|
print("[INFO] Server started")
|
||||||
serve(app, host=HOST, port=PORT)
|
asyncio.run(serve(app, hypercornconfig))
|
||||||
print("[INFO] Server stopped")
|
print("[INFO] Server stopped")
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
flask
|
quart
|
||||||
waitress
|
hypercorn
|
||||||
werkzeug
|
werkzeug
|
|
@ -83,6 +83,21 @@
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #202124;
|
background-color: #202124;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flathubLogo {
|
||||||
|
filter: invert(100%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
background-color: rgba(0, 0, 0, 0) !important;
|
||||||
|
color: var(--text-color)
|
||||||
|
}
|
||||||
|
.mainDiv .yellow {
|
||||||
|
border-color: #e9e98d !important;
|
||||||
|
}
|
||||||
|
.mainDiv .green {
|
||||||
|
border-color: #a9f9a9 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p,
|
p,
|
||||||
|
@ -638,13 +653,6 @@ body {
|
||||||
background-color: #ffffeb;
|
background-color: #ffffeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainDiv img {
|
|
||||||
position: fixed;
|
|
||||||
right: 7vh;
|
|
||||||
top: 8vh;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.links {
|
.links {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.1 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.1 KiB |
|
@ -15,13 +15,17 @@
|
||||||
<div class="mainDiv">
|
<div class="mainDiv">
|
||||||
<div class="startDiv">
|
<div class="startDiv">
|
||||||
<h1 class="w300">PageBurger</h1>
|
<h1 class="w300">PageBurger</h1>
|
||||||
<p>A simple note-taking app!</p>
|
<p>A simple note-taking service!</p>
|
||||||
<br>
|
<br>
|
||||||
<a href="/app">Open in your browser</a>
|
<a href="/app">Open in your browser</a>
|
||||||
<br>
|
|
||||||
<a href="/static/pageburger.mobileconfig" style="margin-top: 5px;">Download for iOS</a>
|
<a href="/static/pageburger.mobileconfig" style="margin-top: 5px;">Download for iOS</a>
|
||||||
|
|
||||||
|
<a style="padding: 0; padding-bottom: 0; margin-top: 5px; background-color: rgba(0, 0, 0, 0);" href="https://flathub.org/apps/org.hectabit.PageBurger">
|
||||||
|
<img class="flathubLogo" style="height: 55px;"src="/static/svg/flathublight.svg">
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<br><br><br>
|
<br>
|
||||||
<div class="feature green">
|
<div class="feature green">
|
||||||
<h7 class="w300">Secure</h7>
|
<h7 class="w300">Secure</h7>
|
||||||
<p2>All your notes are fully end-to-end encrypted. Only you can read your notes, not anyone else.</p2>
|
<p2>All your notes are fully end-to-end encrypted. Only you can read your notes, not anyone else.</p2>
|
||||||
|
|
Loading…
Reference in New Issue