diff --git a/main b/main index f1eb8f9..af0790d 100644 --- a/main +++ b/main @@ -10,6 +10,8 @@ from itertools import groupby from werkzeug.utils import secure_filename 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 flask_limiter import Limiter +from flask_limiter.util import get_remote_address # read config file config = configparser.ConfigParser() @@ -26,6 +28,14 @@ app = Flask(__name__) app.config["SECRET_KEY"] = SECRET_KEY app.config["MAX_CONTENT_LENGTH"] = int(UPLOAD_LIMIT) * 1000 * 1000 +limiter = Limiter( + get_remote_address, + app = app, + default_limits = ["3 per second"], + storage_uri = "memory://", + strategy = "fixed-window" +) + if SECRET_KEY == "placeholder": print("[WARNING] Secret key is not set") @@ -85,8 +95,8 @@ app.jinja_env.globals.update(getUser=get_user) def check_username_taken(username): conn = get_db_connection() - post = conn.execute("SELECT * FROM users WHERE username = ?", - (username,)).fetchone() + post = conn.execute("SELECT * FROM users WHERE lower(username) = ?", + (username.lower(),)).fetchone() conn.close() if post is None: return "error" @@ -125,6 +135,53 @@ def main(): else: return render_template("main.html", posts=posts) +@app.route("/@", methods=("GET", "POST")) +def user(pageusername): + usersession = request.cookies.get("session_DO_NOT_SHARE") + + checkusername = check_username_taken(pageusername) + + if not checkusername == "error": + pageuser = get_user(checkusername) + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + return render_template("user.html", userdata=user, createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) + else: + return render_template("user.html", createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) + else: + return """""", 404 + +@app.route("/@/edit", methods=("GET", "POST")) +def edituser(pageusername): + usersession = request.cookies.get("session_DO_NOT_SHARE") + + checkusername = check_username_taken(pageusername) + + if not checkusername == "error": + pageuser = get_user(checkusername) + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + if pageuser["username"] == user["username"]: + if request.method == "POST": + code = request.form["code"].replace("Content-Security-Policy", "") + conn = get_db_connection() + conn.execute("UPDATE users SET htmldescription = ? WHERE id = ?", + (code, user["id"])) + conn.commit() + conn.close() + return redirect("/@" + user["username"]) + else: + return render_template("edituser.html", userdata=user, pageuser=pageuser) + else: + return """""", 403 + else: + return """""", 403 + else: + return """""", 404 + + @app.route("/api/frontpage", methods=("GET", "POST")) def apifrontpage(): conn = get_db_connection() @@ -332,6 +389,7 @@ def post(): @app.route("/api/comment", methods=("GET", "POST")) +@limiter.limit("1/second", override_defaults=False) def comment(): usersession = request.cookies.get("session_DO_NOT_SHARE") if usersession: @@ -377,12 +435,13 @@ def cdn(filename): @app.route("/signup", methods=("GET", "POST")) +@limiter.limit("5/minute", override_defaults=False) def signup(): usersession = request.cookies.get("session_DO_NOT_SHARE") if usersession: return redirect(url_for("main")) if request.method == "POST": - if not check_username_taken(str(request.form["username"]).lower()) == "error": + if not check_username_taken(request.form["username"]) == "error": flash("Username already taken :3") return redirect(url_for("signup")) @@ -397,8 +456,8 @@ def signup(): hashedpassword = generate_password_hash(request.form["password"]) conn = get_db_connection() - conn.execute("INSERT INTO users (username, password, created) VALUES (?, ?, ?)", - (request.form["username"], hashedpassword, str(time.time()))) + conn.execute("INSERT INTO users (username, password, created, htmldescription) VALUES (?, ?, ?, ?)", + (request.form["username"], hashedpassword, str(time.time()), "")) conn.commit() conn.close() @@ -408,6 +467,7 @@ def signup(): @app.route("/login", methods=("GET", "POST")) +@limiter.limit("10/minute", override_defaults=False) def login(): usersession = request.cookies.get("session_DO_NOT_SHARE") if usersession: @@ -508,6 +568,10 @@ def page_not_found(e): def page_not_found(e): return """""", 400 +@app.errorhandler(429) +def page_not_found(e): + return """""", 429 + @app.errorhandler(404) def page_not_found(e): return """""", 404 diff --git a/requirements.txt b/requirements.txt index a7bab09..c9ec32e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ flask +Flask-Limiter werkzeug waitress \ No newline at end of file diff --git a/schema.sql b/schema.sql index ba5e001..f3409d8 100644 --- a/schema.sql +++ b/schema.sql @@ -9,7 +9,8 @@ CREATE TABLE users ( username TEXT NOT NULL, password TEXT NOT NULL, banned TEXT NOT NULL DEFAULT 0, - administrator INTEGER NOT NULL DEFAULT 0 + administrator INTEGER NOT NULL DEFAULT 0, + htmldescription TEXT NOT NULL ); CREATE TABLE posts ( diff --git a/static/css/style.css b/static/css/style.css index 869b784..593058e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -25,7 +25,32 @@ body { .postDiv { padding-top: 120px; } - +.profileDiv { + padding-left: 10px; + padding-right: 10px; +} +.profileIFrame { + border: solid; + border-width: 0; + border-top-width: 1px; + border-color: rgb(241, 241, 241); + width: 100%; + height: calc(100vh - 295px); +} +.profileDiv .badgeDiv p { + background-color: black; + border-radius: 99px; + color: white; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + display: inline; +} +.editThing .htmlBox { + width: calc(100% - 10px); + height: 300px; + text-align: top; +} .accountform { margin-left: 20%; margin-right: 20%; @@ -85,6 +110,7 @@ body { .post img { min-height: 200px; max-height: 300px; + max-width: 100%; border-radius: 10px; } @@ -131,6 +157,11 @@ body { color: rgb(175, 175, 175); } +.usernamelink { + color: black; + text-decoration: none; +} + .hidden { display: none; } \ No newline at end of file diff --git a/templates/edituser.html b/templates/edituser.html new file mode 100644 index 0000000..ff44fff --- /dev/null +++ b/templates/edituser.html @@ -0,0 +1,41 @@ + + + + + burgercat + + + + + + + + +
+
+ {% if userdata %} + {% if pageuser.id == userdata.id %} +

edit mode

+
+ +

+ +
+ {% endif %} + {% endif %} +
+
+ + + \ No newline at end of file diff --git a/templates/main.html b/templates/main.html index 8bf9951..388a522 100644 --- a/templates/main.html +++ b/templates/main.html @@ -31,7 +31,7 @@
{% for post in posts %}
-

{{ getUser(post["creator"])["username"] }}

+

{{ getUser(post["creator"])["username"] }}

{% if userdata %} {% if userdata.administrator == 1 %} diff --git a/templates/settings.html b/templates/settings.html index 9093d78..05f21ea 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -30,6 +30,7 @@ {% endif %} Logged in as {{ userdata.username }}

+ View my public profile
Log out
diff --git a/templates/user.html b/templates/user.html new file mode 100644 index 0000000..249fcf6 --- /dev/null +++ b/templates/user.html @@ -0,0 +1,51 @@ + + + + + burgercat + + + + + + + + + +
+
+

{{ pageuser.username }}

+
+ {% if pageuser.administrator == 1 %} +

Administrator

+ {% endif %} +
+

Joined on {{ createddate }}

+ {% if userdata %} + {% if pageuser.id == userdata.id %} + edit page +

+ {% endif %} + {% endif %} +
+ +
+ + + + \ No newline at end of file