#!/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 # TODO: 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) 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() # TODO: verify that the uuid was generated by us (otherwise any uuid, # like one generated by the user, would be accepted) 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() 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) if __name__ == '__main__': app.run(host='0.0.0.0')