From e0e13ac59ec75422a5b6ab080c9ac84ac49f78e6 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Fri, 26 Jun 2020 19:29:33 +0200 Subject: [PATCH] move webhost over to UUID to make it nearly impossible to guess at seeds Also introduce zip uploads and store the remaining relevant data, implemention of that still pending --- WebHost/__init__.py | 62 ++++---------- WebHost/models.py | 12 ++- WebHost/templates/host_room.html | 8 +- WebHost/templates/layout.html | 1 + WebHost/templates/macros.html | 10 +++ ...upload_multidata.html => upload_game.html} | 2 +- WebHost/templates/view_seed.html | 10 +-- WebHost/tracker.py | 84 +++++++++---------- WebHost/upload.py | 73 ++++++++++++++++ host.yaml | 2 +- 10 files changed, 162 insertions(+), 102 deletions(-) create mode 100644 WebHost/templates/macros.html rename WebHost/templates/{upload_multidata.html => upload_game.html} (92%) create mode 100644 WebHost/upload.py diff --git a/WebHost/__init__.py b/WebHost/__init__.py index 58a79301..156615c9 100644 --- a/WebHost/__init__.py +++ b/WebHost/__init__.py @@ -1,16 +1,14 @@ """Friendly reminder that if you want to host this somewhere on the internet, that it's licensed under MIT Berserker66 So unless you're Berserker you need to include license information.""" -import json import os import logging import typing import multiprocessing import threading -import zlib from pony.flask import Pony -from flask import Flask, request, redirect, url_for, render_template, Response, session, abort, flash +from flask import Flask, request, redirect, url_for, render_template, Response, session, abort from flask_caching import Cache from flaskext.autoversion import Autoversion @@ -22,13 +20,13 @@ os.makedirs(LOGS_FOLDER, exist_ok=True) def allowed_file(filename): - return filename.endswith('multidata') + return filename.endswith(('multidata', ".zip")) app = Flask(__name__) Pony(app) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER -app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024 # 1 megabyte limit +app.config['MAX_CONTENT_LENGTH'] = 4 * 1024 * 1024 # 4 megabyte limit # if you want persistent sessions on your server, make sure you make this a constant in your config.yaml app.config["SECRET_KEY"] = os.urandom(32) app.config['SESSION_PERMANENT'] = True @@ -78,19 +76,21 @@ class MultiworldInstance(): self.process = None -@app.route('/seed/') -def view_seed(seed: int): +@app.route('/seed/') +def view_seed(seed: UUID): seed = Seed.get(id=seed) - if seed: - return render_template("view_seed.html", seed=seed) - else: + if not seed: abort(404) + return render_template("view_seed.html", seed=seed, + rooms=[room for room in seed.rooms if room.owner == session["_id"]]) -@app.route('/new_room/') -def new_room(seed: int): +@app.route('/new_room/') +def new_room(seed: UUID): seed = Seed.get(id=seed) - room = Room(seed=seed, owner=session["_id"]) + if not seed: + abort(404) + room = Room(seed=seed, owner=session["_id"], tracker=uuid4()) commit() return redirect(url_for("host_room", room=room.id)) @@ -104,8 +104,8 @@ def _read_log(path: str): f"Likely a crash during spinup of multiworld instance or it is still spinning up." -@app.route('/log/') -def display_log(room: int): +@app.route('/log/') +def display_log(room: UUID): # noinspection PyTypeChecker return Response(_read_log(os.path.join("logs", str(room) + ".txt")), mimetype="text/plain;charset=UTF-8") @@ -113,8 +113,8 @@ def display_log(room: int): processstartlock = threading.Lock() -@app.route('/hosted/', methods=['GET', 'POST']) -def host_room(room: int): +@app.route('/hosted/', methods=['GET', 'POST']) +def host_room(room: UUID): room = Room.get(id=room) if room is None: return abort(404) @@ -135,30 +135,4 @@ def host_room(room: int): from WebHost.customserver import run_server_process -from . import tracker # to trigger app routing picking up on it - -@app.route('/', methods=['GET', 'POST']) -def upload_multidata(): - if request.method == 'POST': - # check if the post request has the file part - if 'file' not in request.files: - flash('No file part') - else: - file = request.files['file'] - # if user does not select file, browser also - # submit an empty part without filename - if file.filename == '': - flash('No selected file') - elif file and allowed_file(file.filename): - try: - multidata = json.loads(zlib.decompress(file.read()).decode("utf-8-sig")) - except: - flash("Could not load multidata. File may be corrupted or incompatible.") - else: - seed = Seed(multidata=multidata) - commit() # place into DB and generate ids - return redirect(url_for("view_seed", seed=seed.id)) - else: - flash("Not recognized file format. Awaiting a .multidata file.") - rooms = select(room for room in Room if room.owner == session["_id"]) - return render_template("upload_multidata.html", rooms=rooms) +from . import tracker, upload # to trigger app routing picking up on it diff --git a/WebHost/models.py b/WebHost/models.py index ede7338e..bf34d124 100644 --- a/WebHost/models.py +++ b/WebHost/models.py @@ -7,26 +7,30 @@ db = Database() class Patch(db.Entity): id = PrimaryKey(int, auto=True) + player = Required(int) data = Required(buffer) - simple_seed = Required('Seed') + seed = Optional('Seed') class Room(db.Entity): - id = PrimaryKey(int, auto=True) + id = PrimaryKey(UUID, default=uuid4) last_activity = Required(datetime, default=lambda: datetime.utcnow(), index=True) + creation_time = Required(datetime, default=lambda: datetime.utcnow()) owner = Required(UUID, index=True) commands = Set('Command') seed = Required('Seed', index=True) multisave = Optional(Json) + show_spoiler = Required(int, default=0) # 0 -> never, 1 -> after completion, -> 2 always timeout = Required(int, default=lambda: 6) - allow_tracker = Required(bool, default=True) + tracker = Optional(UUID, index=True) last_port = Optional(int, default=lambda: 0) class Seed(db.Entity): - id = PrimaryKey(int, auto=True) + id = PrimaryKey(UUID, default=uuid4) rooms = Set(Room) multidata = Optional(Json) + owner = Required(UUID, index=True) creation_time = Required(datetime, default=lambda: datetime.utcnow()) patches = Set(Patch) spoiler = Optional(str) diff --git a/WebHost/templates/host_room.html b/WebHost/templates/host_room.html index f6355e91..7946f44c 100644 --- a/WebHost/templates/host_room.html +++ b/WebHost/templates/host_room.html @@ -3,9 +3,11 @@ Multiworld {{ room.id }} {% endblock %} {% block body %} - Room created from Seed #{{ room.seed.id }}
- {% if room.allow_tracker %} - This room has a Multiworld Tracker enabled.
+ {% if room.owner == session["_id"] %} + Room created from Seed #{{ room.seed.id }}
+ {% endif %} + {% if room.tracker %} + This room has a Multiworld Tracker enabled.
{% endif %} This room will be closed after {{ room.timeout }} hours of inactivity. Should you wish to continue later, you can simply refresh this page and the server will be started again.
diff --git a/WebHost/templates/layout.html b/WebHost/templates/layout.html index 5b5b4d9b..296f99e0 100644 --- a/WebHost/templates/layout.html +++ b/WebHost/templates/layout.html @@ -16,6 +16,7 @@ {% endwith %} {% block body %}{% endblock %} +
{# spacing for notice #}