mirror of
https://github.com/csd4ni3l/loginween.git
synced 2026-01-01 04:23:48 +01:00
Make Posts id autoincrement, make working posts page on home which shows the pumpkins and comment, reduce bloat by making a lightbtn setup function, fix XSS
This commit is contained in:
28
app.py
28
app.py
@@ -1,10 +1,11 @@
|
|||||||
from flask import Flask, Response, render_template, redirect, url_for, g, request
|
from flask import Flask, Response, render_template, redirect, url_for, g, request, json
|
||||||
|
|
||||||
from flask_login import LoginManager, login_required
|
from flask_login import LoginManager, login_required
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from pattern import Pattern
|
from pattern import Pattern
|
||||||
|
|
||||||
import sqlite3, os, flask_login, dotenv, secrets
|
import sqlite3, os, flask_login, dotenv, secrets, html
|
||||||
|
|
||||||
if os.path.exists(".env"):
|
if os.path.exists(".env"):
|
||||||
dotenv.load_dotenv(".env")
|
dotenv.load_dotenv(".env")
|
||||||
@@ -31,8 +32,8 @@ def get_db():
|
|||||||
|
|
||||||
db.execute("""
|
db.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS Posts (
|
CREATE TABLE IF NOT EXISTS Posts (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
username TEXT NOT NULL UNIQUE,
|
username TEXT NOT NULL,
|
||||||
comment TEXT NOT NULL,
|
comment TEXT NOT NULL,
|
||||||
pattern TEXT NOT NULL,
|
pattern TEXT NOT NULL,
|
||||||
creation_time INTEGER NOT NULL
|
creation_time INTEGER NOT NULL
|
||||||
@@ -69,13 +70,23 @@ def main():
|
|||||||
|
|
||||||
cur = get_db().cursor()
|
cur = get_db().cursor()
|
||||||
|
|
||||||
cur.execute("SELECT * FROM Posts LIMIT 20")
|
cur.execute("SELECT * FROM Posts LIMIT 15")
|
||||||
|
|
||||||
posts = cur.fetchall()
|
posts = cur.fetchall()
|
||||||
|
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
return render_template("index.jinja2", username=username, posts=posts)
|
for post in posts:
|
||||||
|
if not isinstance(post[0], int):
|
||||||
|
print("Post ID is not int. Exiting for safety.")
|
||||||
|
return "Post ID is not int. Exiting for safety."
|
||||||
|
if not isinstance(post[4], int):
|
||||||
|
print("Post Timestamp is not int. Exiting for safety.")
|
||||||
|
return "Post Timestamp is not int. Exiting for safety."
|
||||||
|
|
||||||
|
new_posts = [[post[0], html.escape(post[1], quote=True), html.escape(post[2], quote=True), [html.escape(f"{pos[0]},{pos[1]}", quote=True) for pos in json.loads(post[3])], datetime.fromtimestamp(post[4]).strftime('%Y-%m-%d %H:%M:%S')] for post in posts]
|
||||||
|
|
||||||
|
return render_template("index.jinja2", username=username, posts=new_posts, grid_size=os.getenv("GRID_SIZE", 15))
|
||||||
|
|
||||||
@app.route("/countdown")
|
@app.route("/countdown")
|
||||||
def countdown():
|
def countdown():
|
||||||
@@ -120,7 +131,10 @@ def register():
|
|||||||
return render_template("register.jinja2", grid_size=os.getenv("GRID_SIZE", 15))
|
return render_template("register.jinja2", grid_size=os.getenv("GRID_SIZE", 15))
|
||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
username = request.form["username"]
|
if request.form["username"] != html.escape(request.form["username"], quote=True):
|
||||||
|
return "No XSS please"
|
||||||
|
|
||||||
|
username = html.escape(request.form["username"], quote=True)
|
||||||
pattern = Pattern.from_str(request.form["pattern"])
|
pattern = Pattern.from_str(request.form["pattern"])
|
||||||
|
|
||||||
cur = get_db().cursor()
|
cur = get_db().cursor()
|
||||||
|
|||||||
@@ -151,6 +151,23 @@ function unlight_pumpkin(ctx, cell_size, currentPattern) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setup_lightbtn(ctx, cell_size, lightbtn_id, pattern) {
|
||||||
|
let lit = { value: false };
|
||||||
|
|
||||||
|
document.getElementById(lightbtn_id).addEventListener('click', function(event) {
|
||||||
|
if (lit.value) {
|
||||||
|
lit.value = false;
|
||||||
|
unlight_pumpkin(ctx, cell_size, pattern);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lit.value = true;
|
||||||
|
light_pumpkin(ctx, cell_size, pattern);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return lit;
|
||||||
|
}
|
||||||
|
|
||||||
function setup_pumpkin(canvas_id, clearbtn_id, lightbtn_id, form_id, pattern_field_id, grid_size, allow_drawing=true) {
|
function setup_pumpkin(canvas_id, clearbtn_id, lightbtn_id, form_id, pattern_field_id, grid_size, allow_drawing=true) {
|
||||||
const canvas = document.getElementById(canvas_id);
|
const canvas = document.getElementById(canvas_id);
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
@@ -160,29 +177,20 @@ function setup_pumpkin(canvas_id, clearbtn_id, lightbtn_id, form_id, pattern_fie
|
|||||||
const CELL_SIZE = canvas.width / GRID_SIZE;
|
const CELL_SIZE = canvas.width / GRID_SIZE;
|
||||||
|
|
||||||
let currentPattern = [];
|
let currentPattern = [];
|
||||||
|
let lit = { value: false };
|
||||||
|
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern);
|
clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (allow_drawing) {
|
if (allow_drawing) {
|
||||||
let lit = false;
|
lit = setup_lightbtn(ctx, CELL_SIZE, lightbtn_id, currentPattern);
|
||||||
document.getElementById(lightbtn_id).addEventListener('click', function(event) {
|
|
||||||
if (lit) {
|
|
||||||
lit = false;
|
|
||||||
unlight_pumpkin(ctx, CELL_SIZE, currentPattern);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lit = true;
|
|
||||||
light_pumpkin(ctx, CELL_SIZE, currentPattern);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let drawing = false;
|
let drawing = false;
|
||||||
canvas.addEventListener('mousedown', () => { drawing = true; });
|
canvas.addEventListener('mousedown', () => { drawing = true; });
|
||||||
canvas.addEventListener('mouseup', () => { drawing = false; });
|
canvas.addEventListener('mouseup', () => { drawing = false; });
|
||||||
canvas.addEventListener('mousemove', (e) => draw(e, ctx, CELL_SIZE, drawing, canvas, currentPattern, lit));
|
canvas.addEventListener('mousemove', (e) => draw(e, ctx, CELL_SIZE, drawing, canvas, currentPattern, lit.value));
|
||||||
canvas.addEventListener('click', (e) => {draw(e, ctx, CELL_SIZE, true, canvas, currentPattern, lit)});
|
canvas.addEventListener('click', (e) => {draw(e, ctx, CELL_SIZE, true, canvas, currentPattern, lit.value)});
|
||||||
|
|
||||||
document.getElementById(clearbtn_id).addEventListener('click', () => clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern));
|
document.getElementById(clearbtn_id).addEventListener('click', () => clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern));
|
||||||
document.getElementById(form_id).addEventListener('submit', function(event) {
|
document.getElementById(form_id).addEventListener('submit', function(event) {
|
||||||
|
|||||||
@@ -90,18 +90,7 @@ img.addEventListener('load', function() {
|
|||||||
setInterval(update, 1500);
|
setInterval(update, 1500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setup_lightbtn(ctx, CELL_SIZE, "lightBtn", pattern.slice(0, pattern.length - last_days));
|
||||||
let lit = false;
|
|
||||||
document.getElementById("lightBtn").addEventListener('click', function(event) {
|
|
||||||
if (lit) {
|
|
||||||
lit = false;
|
|
||||||
unlight_pumpkin(ctx, CELL_SIZE, pattern.slice(0, pattern.length - last_days));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lit = true;
|
|
||||||
light_pumpkin(ctx, CELL_SIZE, pattern.slice(0, pattern.length - last_days));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
@@ -18,15 +18,40 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="position-absolute top-50 start-50 translate-middle text-center">
|
<div class="text-center mt-3">
|
||||||
|
<h1>Posts</h1>
|
||||||
|
</div>
|
||||||
|
<div class="container mt-4">
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<div class="card" style="width: 18rem;">
|
<div class="col">
|
||||||
<canvas class="card-img-top"></canvas>
|
<div class="card h-100">
|
||||||
|
<canvas id="pumpkin-canvas-{{ post.0 }}" width="600" height="600" class="card-img-top"></canvas>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">{{ post.1 }}: {{ post.3 }}</h5>
|
<h5 class="card-title">{{ post.2 }}</h5>
|
||||||
<p class="card-text">{{ post.2 }}</p>
|
<p class="card-text">By: {{ post.1 }}<br>Created at: {{ post.4 }}</p>
|
||||||
|
<button type="button" id="lightBtn-{{ post.0 }}" class="btn btn-warning">Light!</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let CELL_SIZE = 0;
|
||||||
|
|
||||||
|
{% for post in posts %}
|
||||||
|
const [ctx_{{ post.0 }}, canvas_{{ post.0 }}, img_{{ post.0 }}] = setup_pumpkin("pumpkin-canvas-{{ post.0 }}", null, null, null, null, {{ grid_size }}, false);
|
||||||
|
let lit_{{ post.0 }} = false;
|
||||||
|
let pattern_{{ post.0 }} = {{ post.3 }};
|
||||||
|
|
||||||
|
CELL_SIZE = canvas_{{ post.0 }}.width / 15;
|
||||||
|
|
||||||
|
img_{{ post.0 }}.addEventListener('load', function() {
|
||||||
|
unlight_pumpkin(ctx_{{ post.0 }}, CELL_SIZE, pattern_{{ post.0 }});
|
||||||
|
});
|
||||||
|
setup_lightbtn(ctx_{{ post.0 }}, CELL_SIZE, "lightBtn-{{ post.0 }}", pattern_{{ post.0 }})
|
||||||
|
{% endfor %}
|
||||||
|
</script>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
Reference in New Issue
Block a user