diff --git a/Highscore-Server/server/__init__.py b/Highscore-Server/server/__init__.py index 78b7c34..41884ee 100644 --- a/Highscore-Server/server/__init__.py +++ b/Highscore-Server/server/__init__.py @@ -1,16 +1,20 @@ from random import randint + from flask import Flask, render_template, abort from flask_assets import Bundle from werkzeug.exceptions import HTTPException + +from server.config import MIGRATION_DIR, INSTANCE_DIR from server.extensions import db, migrate, cache, assets, login_manager from server.models import Users from server import views, auth, api -app = Flask(__name__) -app.config.from_pyfile('config.py') + +app = Flask(__name__, instance_path=INSTANCE_DIR) +app.config.from_pyfile("config.py") db.init_app(app) -migrate.init_app(app, db) +migrate.init_app(app, db, directory=MIGRATION_DIR) with app.app_context(): db.create_all() @@ -23,7 +27,12 @@ assets.init_app(app) scripts = Bundle("js/*.js", filters="jsmin", output="gen/scripts.js", depends="js/*.js") assets.register("scripts", scripts) -styles = Bundle("sass/style.sass", filters="libsass, cssmin", output="gen/styles.css", depends="sass/*.sass") +styles = Bundle( + "sass/style.sass", + filters="libsass, cssmin", + output="gen/styles.css", + depends="sass/*.sass", +) assets.register("styles", styles) cache.init_app(app) @@ -42,9 +51,8 @@ def error_page(err): if not isinstance(err, HTTPException): abort(500) return ( - render_template("error.html", - error=err.code, - msg=err.description, - image=str(randint(1, 3))), + render_template( + "error.html", error=err.code, msg=err.description, image=str(randint(1, 3)) + ), err.code, ) diff --git a/Highscore-Server/server/api.py b/Highscore-Server/server/api.py index 3213722..1585c91 100644 --- a/Highscore-Server/server/api.py +++ b/Highscore-Server/server/api.py @@ -8,14 +8,14 @@ from server.extensions import db from server.config import BEARER_TOKEN -blueprint = Blueprint('api', __name__, url_prefix='/api') +blueprint = Blueprint("api", __name__, url_prefix="/api") -@blueprint.route('/tokens', methods=['DELETE', 'POST']) +@blueprint.route("/tokens", methods=["DELETE", "POST"]) @login_required def tokens(): - if request.method == 'DELETE': - token_id = request.form['token_id'] + if request.method == "DELETE": + token_id = request.form["token_id"] if not token_id: return jsonify({"error": "No token ID provided!"}), 400 @@ -29,7 +29,7 @@ def tokens(): db.session.commit() return jsonify({"success": "Token deleted!"}), 200 - elif request.method == 'POST': + elif request.method == "POST": if len(Tokens.query.filter_by(holder=current_user.id).all()) >= 5: return jsonify({"error": "You already have 5 tokens!"}), 403 @@ -40,20 +40,20 @@ def tokens(): return jsonify({"success": "Token added!"}), 200 -@blueprint.route('/post', methods=['POST']) +@blueprint.route("/post", methods=["POST"]) def post(): form = request.form if not form: return "Invalid form", 400 - if not request.headers.get('Authentication'): + if not request.headers.get("Authentication"): return "Invalid authentication", 401 - if not isinstance(form['score'], int): + if not isinstance(form["score"], int): return "Score must be an integer", 400 - if int(form['score']) < 0: + if int(form["score"]) < 0: return "Score must be greater than 0", 400 - if form['difficulty'] not in [0, 1, 2, 3, 4]: + if form["difficulty"] not in [0, 1, 2, 3, 4]: # 0 = Easy, Level 1 # 1 = Easy, Level 2 # 2 = Easy, Level 3 @@ -61,32 +61,34 @@ def post(): # 4 = Hard return "Invalid difficulty", 400 - if token_data := Tokens.query.filter_by(token=request.headers.get('Authentication')).first(): + if token_data := Tokens.query.filter_by( + token=request.headers.get("Authentication") + ).first(): # User is authenticated # This is a registered user score = Scores( - score=form['score'], - difficulty=form['difficulty'], - achievements=form['achievements'], + score=form["score"], + difficulty=form["difficulty"], + achievements=form["achievements"], user_id=token_data.holder, ) db.session.add(score) db.session.commit() return "Success!", 200 - elif request.headers.get('Authentication') == BEARER_TOKEN: + elif request.headers.get("Authentication") == BEARER_TOKEN: # User is not authenticated, but has the correct token # This is an anonymous user - if not form['playerName'] or len(form['playerId']) != 4: + if not form["playerName"] or len(form["playerId"]) != 4: return "Invalid player name", 400 score = Scores( anonymous=True, - username=form['playerName'], - score=form['score'], - difficulty=form['difficulty'], + username=form["playerName"], + score=form["score"], + difficulty=form["difficulty"], ) db.session.add(score) db.session.commit() diff --git a/Highscore-Server/server/auth.py b/Highscore-Server/server/auth.py index a187db2..8f3eee5 100644 --- a/Highscore-Server/server/auth.py +++ b/Highscore-Server/server/auth.py @@ -9,18 +9,18 @@ from server.extensions import db from server.models import Users, Tokens -blueprint = Blueprint('auth', __name__) +blueprint = Blueprint("auth", __name__) -@blueprint.route('/auth', methods=['GET']) +@blueprint.route("/auth", methods=["GET"]) def auth(): - return render_template('auth.html') + return render_template("auth.html") -@blueprint.route('/account', methods=['GET']) +@blueprint.route("/account", methods=["GET"]) @login_required def account(): - action = request.args.get('action', None) + action = request.args.get("action", None) if action == "logout": logout_user() @@ -32,10 +32,10 @@ def account(): flash("Insert password change function", "error") token_list = Tokens.query.filter_by(holder=current_user.id).all() - return render_template('account.html', token_list=token_list) + return render_template("account.html", token_list=token_list) -@blueprint.route('/register', methods=['POST']) +@blueprint.route("/register", methods=["POST"]) def register(): # Get the form data username = request.form["username"].strip() @@ -46,7 +46,9 @@ def register(): # Validate the form if not username or not username_regex.match(username): - error.append("Username is empty or invalid! Must be alphanumeric, and can contain ._-") + error.append( + "Username is empty or invalid! Must be alphanumeric, and can contain ._-" + ) if not password: error.append("Password is empty!") elif len(password) < 8: @@ -63,7 +65,7 @@ def register(): register_user = Users( alt_id=str(uuid.uuid4()), username=username, - password=generate_password_hash(password, method="scrypt") + password=generate_password_hash(password, method="scrypt"), ) db.session.add(register_user) db.session.commit() @@ -72,7 +74,7 @@ def register(): return redirect(url_for("auth.auth")) -@blueprint.route('/login', methods=['POST']) +@blueprint.route("/login", methods=["POST"]) def login(): # Get the form data username = request.form["username"].strip() diff --git a/Highscore-Server/server/config.py b/Highscore-Server/server/config.py index 0bc4249..b41e3b3 100644 --- a/Highscore-Server/server/config.py +++ b/Highscore-Server/server/config.py @@ -1,20 +1,24 @@ import os + # Purely to make the code a bit more readable def env(key): return os.getenv(key) -SECRET_KEY = env('FLASK_KEY') -BEARER_TOKEN = env('BEARER_TOKEN') -user = env('DB_USER') -password = env('DB_PASSWORD') -host = env('DB_HOST') -database = env('DB_NAME') +SECRET_KEY = env("FLASK_KEY") +BEARER_TOKEN = env("BEARER_TOKEN") -SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{user}:{password}@{host}:5432/{database}" +user = env("DB_USER") +password = env("DB_PASSWORD") +host = env("DB_HOST") +database = env("DB_NAME") + +SQLALCHEMY_DATABASE_URI = ( + f"postgresql+psycopg2://{user}:{password}@{host}:5432/{database}" +) SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_POOL_RECYCLE = 621 -MIGRATION_DIR = '/data/storage/migrations' -INSTANCE_DIR = '/data/storage/instance' \ No newline at end of file +MIGRATION_DIR = "/data/storage/migrations" +INSTANCE_DIR = "/data/storage/instance" diff --git a/Highscore-Server/server/extensions.py b/Highscore-Server/server/extensions.py index b3014c9..9916969 100644 --- a/Highscore-Server/server/extensions.py +++ b/Highscore-Server/server/extensions.py @@ -7,5 +7,5 @@ from flask_login import LoginManager db = SQLAlchemy() migrate = Migrate() assets = Environment() -cache = Cache(config={'CACHE_TYPE': 'simple'}) +cache = Cache(config={"CACHE_TYPE": "simple"}) login_manager = LoginManager() diff --git a/Highscore-Server/server/models.py b/Highscore-Server/server/models.py index 720da0b..c10687a 100644 --- a/Highscore-Server/server/models.py +++ b/Highscore-Server/server/models.py @@ -12,6 +12,7 @@ class Scores(db.Model): Scores supports anonymous posting, and instead just wants to post a score, then the username must be provided.Otherwise, it's grabbed from the user table """ + __tablename__ = "scores" id = db.Column(db.Integer, primary_key=True) @@ -27,13 +28,14 @@ class Scores(db.Model): server_default=db.func.now(), ) - scorer = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) + scorer = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True) class Users(db.Model, UserMixin): """ User table """ + __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) @@ -47,8 +49,8 @@ class Users(db.Model, UserMixin): server_default=db.func.now(), ) - scores = db.relationship('Scores', backref='user', lazy=True) - tokens = db.relationship('Tokens', backref='user', lazy=True) + scores = db.relationship("Scores", backref="user", lazy=True) + tokens = db.relationship("Tokens", backref="user", lazy=True) def get_id(self): return str(self.alt_id) @@ -58,10 +60,11 @@ class Tokens(db.Model): """ Token table """ + __tablename__ = "tokens" id = db.Column(db.Integer, primary_key=True) - holder = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) + holder = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) token = db.Column(db.String, nullable=False, unique=True) created_at = db.Column( db.DateTime, diff --git a/Highscore-Server/server/static/sass/style.sass b/Highscore-Server/server/static/sass/style.sass index 4d42e24..719ae6d 100644 --- a/Highscore-Server/server/static/sass/style.sass +++ b/Highscore-Server/server/static/sass/style.sass @@ -9,6 +9,8 @@ $darkBlue: var(--darkBlue) @mixin button($color) text-decoration: none + text-align: center + white-space: nowrap background-color: RGBA($color, 0.02) color: RGB($color) border-radius: 2px diff --git a/Highscore-Server/server/views.py b/Highscore-Server/server/views.py index 34e22e7..9be956c 100644 --- a/Highscore-Server/server/views.py +++ b/Highscore-Server/server/views.py @@ -2,22 +2,23 @@ from flask import Blueprint, request, render_template from server.models import Scores -blueprint = Blueprint('views', __name__) +blueprint = Blueprint("views", __name__) -@blueprint.route('/') +@blueprint.route("/") # @cache.cached(timeout=60) def index(): - difficulty = request.args.get('diff', 0) + difficulty = request.args.get("diff", 0) - top_scores = (Scores.query - .order_by(Scores.score.desc()) - .filter_by(difficulty=difficulty) - .limit(10) - .all()) - return render_template('scores.html', top_scores=top_scores) + top_scores = ( + Scores.query.order_by(Scores.score.desc()) + .filter_by(difficulty=difficulty) + .limit(10) + .all() + ) + return render_template("scores.html", top_scores=top_scores) -@blueprint.route('/about') +@blueprint.route("/about") def about(): - return render_template('about.html') + return render_template("about.html")