2019-06-02 18:20:55 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
The overwrought server, for exchanging mods from master to slave recipients.
|
|
|
|
"""
|
2019-06-02 19:51:32 -04:00
|
|
|
import os
|
2019-06-02 18:20:55 -04:00
|
|
|
import json
|
2019-06-03 07:04:50 -04:00
|
|
|
import getpass
|
2019-06-02 18:20:55 -04:00
|
|
|
import sqlite3
|
|
|
|
import threading
|
|
|
|
|
|
|
|
from passlib.hash import argon2
|
|
|
|
from flask import Flask, send_file, request, abort
|
|
|
|
|
|
|
|
import config_server
|
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
app.config['db_lock'] = threading.Lock()
|
2019-06-02 19:51:32 -04:00
|
|
|
os.makedirs('mods', exist_ok=True)
|
|
|
|
|
|
|
|
def init_db():
|
|
|
|
"""
|
|
|
|
If no database is found, a dummy database is created to allow the
|
|
|
|
initial modpack upload to go smoothly.
|
|
|
|
"""
|
|
|
|
con = sqlite3.connect('modpack.db')
|
|
|
|
cur = con.cursor()
|
|
|
|
try:
|
|
|
|
cur.execute("SELECT filename FROM mod").fetchone()
|
|
|
|
except sqlite3.OperationalError:
|
|
|
|
cur.execute("CREATE TABLE mod(filename TEXT)")
|
|
|
|
con.commit()
|
|
|
|
con.close()
|
|
|
|
init_db()
|
2019-06-02 18:20:55 -04:00
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
"""
|
|
|
|
Main index page. Displays the mod summary page.
|
|
|
|
"""
|
|
|
|
return send_file(config_server.modpack_name + '.html')
|
|
|
|
|
|
|
|
@app.route('/get')
|
|
|
|
def get():
|
|
|
|
"""
|
|
|
|
Returns all mod file entries contained in the database as JSON.
|
|
|
|
Determing which files to update is left as an exercise up to the
|
|
|
|
client.
|
|
|
|
"""
|
|
|
|
app.config.get('db_lock').acquire()
|
|
|
|
con = sqlite3.connect('modpack.db')
|
2019-06-02 20:28:30 -04:00
|
|
|
cur = con.cursor()
|
2019-06-02 18:20:55 -04:00
|
|
|
mods = cur.execute('SELECT filename FROM mod').fetchall()
|
|
|
|
app.config.get('db_lock').release()
|
|
|
|
|
|
|
|
mods = [mod[0] for mod in mods]
|
|
|
|
return json.dumps(mods)
|
|
|
|
|
|
|
|
@app.route('/post', methods=['POST'])
|
|
|
|
def post():
|
|
|
|
"""
|
|
|
|
Allows the modpack owner to upload new mods and a new database to the
|
|
|
|
server. Owner must be validated.
|
|
|
|
"""
|
|
|
|
password = request.form.get('password')
|
|
|
|
if not argon2.verify(password, config_server.pw_hash):
|
|
|
|
abort(401)
|
|
|
|
|
2019-06-02 20:10:00 -04:00
|
|
|
files = request.files.to_dict()
|
2019-06-02 20:28:30 -04:00
|
|
|
if 'modpack.db' in files.keys():
|
|
|
|
db = request.files.get('modpack.db')
|
2019-06-02 20:10:00 -04:00
|
|
|
app.config.get('db_lock').acquire()
|
|
|
|
db.save('modpack.db')
|
|
|
|
app.config.get('db_lock').release()
|
|
|
|
files.pop('modpack.db')
|
2019-06-02 18:20:55 -04:00
|
|
|
|
2019-06-02 20:28:30 -04:00
|
|
|
if config_server.modpack_name + '.html' in files.keys():
|
2019-06-02 20:10:00 -04:00
|
|
|
summary = request.files.get(config_server.modpack_name + '.html')
|
|
|
|
summary.save(config_server.modpack_name + '.html')
|
|
|
|
files.pop(config_server.modpack_name + '.html')
|
2019-06-02 18:26:07 -04:00
|
|
|
|
2019-06-02 20:10:00 -04:00
|
|
|
for fname, file in files.items():
|
2019-06-02 18:20:55 -04:00
|
|
|
file.save(os.path.join(config_server.mods_dir, fname))
|
2019-06-02 20:28:30 -04:00
|
|
|
return "Success!"
|
2019-06-02 18:20:55 -04:00
|
|
|
|
2019-06-03 07:04:50 -04:00
|
|
|
def generate_hash(password=None):
|
2019-06-02 18:20:55 -04:00
|
|
|
"""
|
|
|
|
A utility for generating an argon2 password hash.
|
|
|
|
"""
|
2019-06-03 07:04:50 -04:00
|
|
|
if not password:
|
|
|
|
password = getpass.getpass()
|
2019-06-02 18:20:55 -04:00
|
|
|
pw_hash = argon2.hash(password)
|
|
|
|
return pw_hash
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="The overwrought server. Use gunicorn to start."
|
|
|
|
)
|
2019-06-02 19:11:16 -04:00
|
|
|
parser.add_argument(
|
2019-06-02 18:20:55 -04:00
|
|
|
'action',
|
|
|
|
choices=['hash'],
|
|
|
|
help="What action to perform.",
|
|
|
|
)
|
2019-06-02 19:11:16 -04:00
|
|
|
args = parser.parse_args()
|
2019-06-02 18:20:55 -04:00
|
|
|
|
|
|
|
if args.action == "hash":
|
2019-06-03 07:04:50 -04:00
|
|
|
pw_hash = generate_hash()
|
2019-06-02 18:20:55 -04:00
|
|
|
print(pw_hash)
|