#!/usr/bin/env python3 """ The overwrought server, for exchanging mods from master to slave recipients. """ import json 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() @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') cur = sqlite3.cursor() 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) db = request.files.get('database') app.config.get('db_lock').acquire() db.save('modpack.db') app.config.get('db_lock').release() for fname, file in request.files.items(): if fname == 'modpack.db': continue file.save(os.path.join(config_server.mods_dir, fname)) def generate_hash(password): """ A utility for generating an argon2 password hash. """ pw_hash = argon2.hash(password) return pw_hash if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description="The overwrought server. Use gunicorn to start." ) parse.add_argument( 'action', choices=['hash'], help="What action to perform.", ) parse.add_argument( 'target', help="The target to perform the action on." ) args.parse_args() if args.action == "hash": pw_hash = generate_hash(args.target) print(pw_hash)