This commit is contained in:
maaa 2023-07-09 22:00:15 +02:00
parent f7d22cf36c
commit ad0fdeba35
8 changed files with 198 additions and 8 deletions

74
main
View File

@ -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("/@<pageusername>", 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 """<img src="https://http.cat/images/404.jpg">""", 404
@app.route("/@<pageusername>/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 """<img src="https://http.cat/images/403.jpg">""", 403
else:
return """<img src="https://http.cat/images/403.jpg">""", 403
else:
return """<img src="https://http.cat/images/404.jpg">""", 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 """<img src="https://http.cat/images/400.jpg">""", 400
@app.errorhandler(429)
def page_not_found(e):
return """<img src="https://http.cat/images/429.jpg">""", 429
@app.errorhandler(404)
def page_not_found(e):
return """<img src="https://http.cat/images/404.jpg">""", 404

View File

@ -1,3 +1,4 @@
flask
Flask-Limiter
werkzeug
waitress

View File

@ -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 (

View File

@ -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;
}

41
templates/edituser.html Normal file
View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>burgercat</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
</head>
<body>
<div class="navbar">
<h1>burgercat</h1>
<a class="selected" href="/">home</a>
<a href="/post">post</a>
{% if userdata %}
<a href="/settings/logout" class="right r">log out</a>
<a href="/settings" class="right">{{ userdata.username }}</a>
{% else %}
<a href="/signup" class="right r">sign up</a>
<a href="/login" class="right">log in</a>
{% endif %}
</div>
<div class="postDiv">
<div class="profileDiv">
{% if userdata %}
{% if pageuser.id == userdata.id %}
<h2>edit mode</h2>
<form class="editThing" method="post" enctype="multipart/form-data">
<textarea class="htmlBox" name="code" type="text" placeholder="<p>Hello World!</p>">{{ userdata.htmldescription }}</textarea>
<br><br>
<input class="submit" type="submit" value="save">
</form>
{% endif %}
{% endif %}
</div>
</div>
</body>
</html>

View File

@ -31,7 +31,7 @@
<div class="postDiv">
{% for post in posts %}
<div class="post" id="post">
<p class="username">{{ getUser(post["creator"])["username"] }}</p>
<p><a href='/@{{ getUser(post["creator"])["username"] }}' class="username usernamelink">{{ getUser(post["creator"])["username"] }}</a></p>
<p class="date" id='timestamp_{{post["id"]}}'> </p>
{% if userdata %}
{% if userdata.administrator == 1 %}

View File

@ -30,6 +30,7 @@
{% endif %}
Logged in as {{ userdata.username }}
<br><br>
<a href="/@{{ userdata.username }}">View my public profile</a><br>
<a href="/settings/logout">Log out</a>
</div>
</div>

51
templates/user.html Normal file
View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>burgercat</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self' fonts.gstatic.com fonts.googleapis.com" />
</head>
<body>
<div class="navbar">
<h1>burgercat</h1>
<a class="selected" href="/">home</a>
<a href="/post">post</a>
{% if userdata %}
<a href="/settings/logout" class="right r">log out</a>
<a href="/settings" class="right">{{ userdata.username }}</a>
{% else %}
<a href="/signup" class="right r">sign up</a>
<a href="/login" class="right">log in</a>
{% endif %}
</div>
<div class="postDiv">
<div class="profileDiv">
<h2>{{ pageuser.username }}</h2>
<div class="badgeDiv">
{% if pageuser.administrator == 1 %}
<p>Administrator</p>
{% endif %}
</div>
<p>Joined on {{ createddate }}</p>
{% if userdata %}
{% if pageuser.id == userdata.id %}
<a style="color: rgb(104, 104, 104); text-decoration: none;" href="/@{{ userdata.username }}/edit">edit page</a>
<br><br>
{% endif %}
{% endif %}
</div>
<iframe class="profileIFrame" sandbox="" srcdoc="{{ pageuser.htmldescription }}"></iframe>
</div>
<style>
body {
overflow-y: hidden
}
</style>
</body>
</html>