WebHost: Add a yaml checker

This commit is contained in:
Fabian Dill 2020-07-27 04:05:42 +02:00
parent 89cea382ea
commit 63cbdb9449
5 changed files with 112 additions and 9 deletions

View File

@ -15,11 +15,6 @@ UPLOAD_FOLDER = os.path.relpath('uploads')
LOGS_FOLDER = os.path.relpath('logs') LOGS_FOLDER = os.path.relpath('logs')
os.makedirs(LOGS_FOLDER, exist_ok=True) os.makedirs(LOGS_FOLDER, exist_ok=True)
def allowed_file(filename):
return filename.endswith(('multidata', ".zip"))
app = Flask(__name__) app = Flask(__name__)
Pony(app) Pony(app)
@ -35,8 +30,11 @@ 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 # 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["SECRET_KEY"] = os.urandom(32)
app.config['SESSION_PERMANENT'] = True app.config['SESSION_PERMANENT'] = True
app.config[
"WAITRESS_THREADS"] = 10 # waitress uses one thread for I/O, these are for processing of views that then get sent # waitress uses one thread for I/O, these are for processing of views that then get sent
# berserkermulti.world uses gunicorn + nginx; ignoring this option
app.config["WAITRESS_THREADS"] = 10
#a default that just works. berserkermulti.world runs on mariadb
app.config["PONY"] = { app.config["PONY"] = {
'provider': 'sqlite', 'provider': 'sqlite',
'filename': os.path.abspath('db.db3'), 'filename': os.path.abspath('db.db3'),
@ -111,4 +109,4 @@ def host_room(room: UUID):
from WebHostLib.customserver import run_server_process from WebHostLib.customserver import run_server_process
from . import tracker, upload, landing # to trigger app routing picking up on it from . import tracker, upload, landing, check # to trigger app routing picking up on it

66
WebHostLib/check.py Normal file
View File

@ -0,0 +1,66 @@
import zipfile
from flask import request, flash, redirect, url_for, session, render_template
from WebHostLib import app
banned_zip_contents = (".sfc",)
def allowed_file(filename):
return filename.endswith(('.txt', ".yaml", ".zip"))
from Mystery import roll_settings
from Utils import parse_yaml
@app.route('/mysterycheck', methods=['GET', 'POST'])
def mysterycheck():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
else:
options = {}
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):
if file.filename.endswith(".zip"):
with zipfile.ZipFile(file, 'r') as zfile:
infolist = zfile.infolist()
for file in infolist:
if file.filename.endswith(banned_zip_contents):
return "Uploaded data contained a rom file, which is likely to contain copyrighted material. Your file was deleted."
elif file.filename.endswith(".yaml"):
options[file.filename] = zfile.open(file, "r").read()
elif file.filename.endswith(".txt"):
options[file.filename] = zfile.open(file, "r").read()
else:
options = {file.filename: file.read()}
if not options:
flash("Did not find a .yaml file to process.")
else:
results = {}
for filename, text in options.items():
try:
yaml_data = parse_yaml(text)
except Exception as e:
results[filename] = f"Failed to parse YAML data in {filename}: {e}"
else:
try:
roll_settings(yaml_data)
except Exception as e:
results[filename] = f"Failed to generate mystery in {filename}: {e}"
else:
results[filename] = "Looks fine"
return render_template("checkresult.html", results=results)
else:
flash("Not recognized file format. Awaiting a .yaml file.")
return render_template("check.html")

View File

@ -0,0 +1,23 @@
{% extends 'layout.html' %}
{% block head %}
{{ super() }}
<title>Mystery Check Result</title>
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("uploads.css") }}" />
<script type="application/ecmascript" src="{{ static_autoversion("uploads.js") }}"></script>
{% endblock %}
{% block body %}
<div id="uploads-wrapper">
<div id="uploads" class="main-content">
<h3>Upload Yaml</h3>
<p>This page checks a .yaml file for you, to be used as options for a mystery multiworld. You can also upload a .zip with multiple YAMLs.</p>
<div id="uploads-form-wrapper">
<form id="upload-form" method="post" enctype="multipart/form-data">
<input id="file-input" type="file" name="file">
</form>
<button id="upload-button">Upload</button>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends 'layout.html' %}
{% block head %}
{{ super() }}
<title>Upload Mystery YAML</title>
{% endblock %}
{% block body %}
{% for filename, resulttext in results.items() %}
<span>{{ filename }}: {{ resulttext }}</span><br>
{% endfor %}
{% endblock %}

View File

@ -6,7 +6,7 @@ import logging
from flask import request, flash, redirect, url_for, session, render_template from flask import request, flash, redirect, url_for, session, render_template
from pony.orm import commit, select from pony.orm import commit, select
from WebHostLib import app, allowed_file, Seed, Room, Patch from WebHostLib import app, Seed, Room, Patch
accepted_zip_contents = {"patches": ".bmbp", accepted_zip_contents = {"patches": ".bmbp",
"spoiler": ".txt", "spoiler": ".txt",
@ -71,3 +71,7 @@ def uploads():
flash("Not recognized file format. Awaiting a .multidata file.") flash("Not recognized file format. Awaiting a .multidata file.")
rooms = select(room for room in Room if room.owner == session["_id"]) rooms = select(room for room in Room if room.owner == session["_id"])
return render_template("uploads.html", rooms=rooms) return render_template("uploads.html", rooms=rooms)
def allowed_file(filename):
return filename.endswith(('multidata', ".zip"))