attendance-flask-mini-app/main.py

63 lines
2.0 KiB
Python
Executable File

#!/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('/<uuid:id>')
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')