diff --git a/TFR/requirements.txt b/TFR/requirements.txt index 58c8de8..1765fc5 100644 --- a/TFR/requirements.txt +++ b/TFR/requirements.txt @@ -1,3 +1,4 @@ +Pillow Gunicorn psycopg2-binary shortuuid diff --git a/TFR/server/account.py b/TFR/server/account.py index 519f378..8a5e989 100644 --- a/TFR/server/account.py +++ b/TFR/server/account.py @@ -1,11 +1,19 @@ import uuid import re +import os from flask import Blueprint, request, render_template, flash, redirect, url_for from flask_login import login_required, current_user, logout_user from werkzeug.security import generate_password_hash, check_password_hash -from .config import USER_REGEX, USER_EMAIL_REGEX +from .config import ( + USER_REGEX, + USER_EMAIL_REGEX, + UPLOAD_EXTENSIONS, + UPLOAD_RESOLUTION, + UPLOAD_MAX_SIZE, + UPLOAD_DIR, +) from .models import Users, Sessions, Scores, ProfileTags, PasswordReset from .extensions import db @@ -29,7 +37,30 @@ def settings(): if not check_password_hash(user.password, password): flash("Password is incorrect!", "error") - return redirect(url_for('account.settings')) + return redirect(url_for("account.settings")) + + if "file" in request.files and request.files['file'].filename: + picture = request.files["file"] + file_ext = picture.filename.split(".")[-1] + file_name = f"{user.id}.{file_ext}" + + if file_ext not in UPLOAD_EXTENSIONS: + error.append("Picture is not a valid image!") + if picture.content_length > UPLOAD_MAX_SIZE: + error.append( + f"Picture is too large! Must be less than {UPLOAD_EXTENSIONS / 1000000}MB!" + ) + + if error: + for err in error: + flash(err, "error") + return redirect(url_for("account.settings")) + + if user.picture: + os.remove(os.path.join(UPLOAD_DIR, user.picture)) + + user.picture = file_name + picture.save(os.path.join(UPLOAD_DIR, file_name)) if username: if user_regex.match(username): @@ -79,7 +110,9 @@ def password_reset(): if not check_password_hash(user.password, current): error.append("Current password is incorrect!") if len(new) < 8: - error.append("New password is too short! Must be at least 8 characters long.") + error.append( + "New password is too short! Must be at least 8 characters long." + ) if new != confirm: error.append("New passwords do not match!") diff --git a/TFR/server/api.py b/TFR/server/api.py index 47b91e3..52d7243 100644 --- a/TFR/server/api.py +++ b/TFR/server/api.py @@ -1,9 +1,10 @@ import re import shortuuid -from flask import Blueprint, request, jsonify +from flask import Blueprint, request, jsonify, send_from_directory from flask_login import login_required, current_user from werkzeug.security import check_password_hash +from werkzeug.utils import secure_filename from .models import Scores, Sessions, Users from .extensions import db @@ -11,12 +12,19 @@ from .config import ( GAME_DIFFICULTIES, MAX_SEARCH_RESULTS, USER_REGEX, + UPLOAD_DIR, ) blueprint = Blueprint("api", __name__, url_prefix="/api") +@blueprint.route("/uploads/", methods=["GET"]) +def upload_dir(filename): + filename = secure_filename(filename) + return send_from_directory(UPLOAD_DIR, filename) + + @blueprint.route("/tokens", methods=["POST"]) @login_required def tokens(): @@ -58,6 +66,10 @@ def post(): if int(difficulty) not in GAME_DIFFICULTIES: return "Invalid difficulty!" + # This is a fix for a bug in the game that we dunno how to actually fix + # Yupeeeeeeeeee + if score < 10: + return "Score is impossible!" session_data = Sessions.query.filter_by(auth_key=session_key).first() if not session_data: diff --git a/TFR/server/config.py b/TFR/server/config.py index b612d79..2a4a59d 100644 --- a/TFR/server/config.py +++ b/TFR/server/config.py @@ -1,6 +1,11 @@ -import os +from os import getenv +UPLOAD_DIR = "/data/uploads" +UPLOAD_EXTENSIONS = ["png", "jpg", "jpeg", "gif"] +UPLOAD_RESOLUTION = (512, 512) +UPLOAD_MAX_SIZE = 3 * 1024 * 1024 # 3MB + GAME_VERSION = "alpha" GAME_VERSIONS = ["alpha"] GAME_DIFFICULTIES = [0, 1, 2, 3, 4] @@ -12,12 +17,12 @@ MAX_TOP_SCORES = 15 MAX_SEARCH_RESULTS = 5 # Postgres -SECRET_KEY = os.getenv("FLASK_KEY") +SECRET_KEY = getenv("FLASK_KEY") -user = os.getenv("DB_USER") -password = os.getenv("DB_PASSWORD") -host = os.getenv("DB_HOST") -db = os.getenv("DB_NAME") +user = getenv("DB_USER") +password = getenv("DB_PASSWORD") +host = getenv("DB_HOST") +db = getenv("DB_NAME") SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{user}:{password}@{host}:5432/{db}" SQLALCHEMY_TRACK_MODIFICATIONS = False diff --git a/TFR/server/static/images/pfp.png b/TFR/server/static/images/pfp.png new file mode 100644 index 0000000..fc01a46 Binary files /dev/null and b/TFR/server/static/images/pfp.png differ diff --git a/TFR/server/templates/views/account_settings.html b/TFR/server/templates/views/account_settings.html index 1d82ab6..d56efcf 100644 --- a/TFR/server/templates/views/account_settings.html +++ b/TFR/server/templates/views/account_settings.html @@ -4,12 +4,16 @@ {% block content %}

Profile Settings

-
+
- Profile picture + {% if current_user.picture %} + Profile picture + {% else %} + Profile picture + {% endif %} - +
{{ text(id="profile-username", name="username", value=current_user.username) }} diff --git a/TFR/server/views.py b/TFR/server/views.py index 0abe51f..e6bbc36 100644 --- a/TFR/server/views.py +++ b/TFR/server/views.py @@ -19,7 +19,7 @@ def index(): scores = db.session.query(Scores).filter_by(difficulty=diff_arg) subquery = ( - db.session.query(Scores.user_id, func.min(Scores.score).label('min')) + db.session.query(Scores.user_id, func.min(Scores.score).label("min")) .group_by(Scores.user_id) .subquery() ) @@ -28,9 +28,8 @@ def index(): scores = scores.filter_by(version=ver_arg) if not user_arg: - scores = ( - scores.join(subquery, Scores.user_id == subquery.c.user_id) - .filter(Scores.score == subquery.c.min) + scores = scores.join(subquery, Scores.user_id == subquery.c.user_id).filter( + Scores.score == subquery.c.min ) else: user = Users.query.filter_by(username=user_arg).first() @@ -42,11 +41,7 @@ def index(): scores = scores.order_by(Scores.score.asc()).limit(MAX_TOP_SCORES).all() return render_template( - "views/scores.html", - scores=scores, - diff=int(diff_arg), - ver=ver_arg, - user=user + "views/scores.html", scores=scores, diff=int(diff_arg), ver=ver_arg, user=user ) diff --git a/docker-compose.yml b/docker-compose.yml index 7de16b7..7fde659 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,7 @@ services: restart: unless-stopped volumes: - ./TFR/storage/migrations:/data/migrations + - ./TFR/storage/uploads:/data/uploads environment: FLASK_KEY: ${THE_FRONT_ROOMS_SECRETE_KEY} DB_USER: ${POSTGRES_USER}