#!/usr/bin/env python3 import uuid import sqlite3 from datetime import datetime from flask import Flask, request, render_template from flask_uuid import FlaskUUID from flask_qrcode import QRcode from flask_socketio import SocketIO from werkzeug.middleware.proxy_fix import ProxyFix # WIP: use sockets to broadcast when a hit to the expected uuid has been # received, so that connected clients (the Chromium public browser) can # refresh the qr code and update the list of users # https://flask-socketio.readthedocs.io app = Flask(__name__) FlaskUUID(app) QRcode(app) app.config['SECRET_KEY'] = '53a8373e7ae652cd38beba15454b1dc4' #app = ProxyFix(app, x_for=1, x_host=1) app.wsgi_app = ProxyFix(app.wsgi_app) socketio = SocketIO(app, async_mode=None) def get_db_connection(): conn = sqlite3.connect('database.db') conn.row_factory = sqlite3.Row return conn @app.route('/') def show_qr_and_list(): # TODO: reject direct connections to server; allow access only via proxy conn = get_db_connection() data = conn.execute('SELECT * FROM hits ORDER BY id DESC LIMIT 10').fetchall() conn.close() # TODO: next_ uuid should be in global state, to verify it when it's received return render_template("template.html", next_uuid=str(uuid.uuid1()), hits=data) @app.route('/') def catch_uuids(id): ua = request.headers.get('Remote-User') # TODO: Check directly with Authelia using https://auth.agofer.net/api/verify time = datetime.now().strftime("%A %Y-%m-%d %H:%M:%S") error = None data = [] conn = get_db_connection() existing = conn.execute( 'SELECT * FROM hits WHERE uuid = ?', (str(id),)).fetchone() existing = False # Temporary, for easier development if id.fields[5] != uuid.getnode(): error = 'DIFFERENT_NODE' if not ua: error = 'NO_USERNAME' elif existing: error = 'ALREADY_USED' else: conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua)) conn.commit() socketio.emit('qr_used', {'data': (time, ua, str(id))}) data = conn.execute( 'SELECT * FROM hits WHERE user = ? ORDER BY id DESC LIMIT 10', (ua,) ).fetchall() conn.close() return render_template('thanks.html', user=ua, time=time, error=error, hits=data) @socketio.on('message') def handle_message(data): print('received message: ' + data) @socketio.on('my_event') def handle_my_custom_event(json): print('received json: ' + str(json)) if __name__ == '__main__': #app.run(host='0.0.0.0') socketio.run(app, host='0.0.0.0')