Uses websockets to refresh the page when QR code scanned

This commit is contained in:
Jorge Enrique Gómez Gómez 2022-07-28 21:13:34 +00:00
parent 912f84597d
commit c5200805e1
4 changed files with 72 additions and 13 deletions

View File

@ -14,3 +14,20 @@ To create an empty `database.db` sqlite file with the table described in
```bash ```bash
./init_db.py ./init_db.py
``` ```
## Nginx reverse proxy configuration
Add this code to the nginx configuration file for the virtual host:
```nginx
location /socket.io {
set $webapp http://attendance.lxd:5000;
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass $webapp;
}
```

27
main.py
View File

@ -6,7 +6,10 @@ from datetime import datetime
from flask import Flask, request, render_template from flask import Flask, request, render_template
from flask_uuid import FlaskUUID from flask_uuid import FlaskUUID
from flask_qrcode import QRcode from flask_qrcode import QRcode
# TODO: use sockets to broadcast when a hit to the expected uuid has been 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 # received, so that connected clients (the Chromium public browser) can
# refresh the qr code and update the list of users # refresh the qr code and update the list of users
# https://flask-socketio.readthedocs.io # https://flask-socketio.readthedocs.io
@ -14,6 +17,10 @@ from flask_qrcode import QRcode
app = Flask(__name__) app = Flask(__name__)
FlaskUUID(app) FlaskUUID(app)
QRcode(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(): def get_db_connection():
conn = sqlite3.connect('database.db') conn = sqlite3.connect('database.db')
@ -42,8 +49,9 @@ def catch_uuids(id):
conn = get_db_connection() conn = get_db_connection()
existing = conn.execute( existing = conn.execute(
'SELECT * FROM hits WHERE uuid = ?', (str(id),)).fetchone() 'SELECT * FROM hits WHERE uuid = ?', (str(id),)).fetchone()
# TODO: verify that the uuid was generated by us (otherwise any uuid, existing = False # Temporary, for easier development
# like one generated by the user, would be accepted) if id.fields[5] != uuid.getnode():
error = 'DIFFERENT_NODE'
if not ua: if not ua:
error = 'NO_USERNAME' error = 'NO_USERNAME'
elif existing: elif existing:
@ -51,6 +59,8 @@ def catch_uuids(id):
else: else:
conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua)) conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua))
conn.commit() conn.commit()
socketio.emit('qr_used', {'data': (time, ua, str(id))})
data = conn.execute( data = conn.execute(
'SELECT * FROM hits WHERE user = ? ORDER BY id DESC LIMIT 10', (ua,) 'SELECT * FROM hits WHERE user = ? ORDER BY id DESC LIMIT 10', (ua,)
).fetchall() ).fetchall()
@ -58,5 +68,14 @@ def catch_uuids(id):
return render_template('thanks.html', user=ua, time=time, error=error, hits=data) 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__': if __name__ == '__main__':
app.run(host='0.0.0.0') #app.run(host='0.0.0.0')
socketio.run(app, host='0.0.0.0')

View File

@ -1,18 +1,38 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Example</title> <script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var socket = io();
socket.on('connect', function() {
socket.emit('my_event', {data: 'Connected to server'});
});
socket.on('qr_used', function(msg, cb) {
location.reload(true);
/*
$('#log').append('<li>' + msg.data[0] + ': ' + msg.data[1] + ' (' + msg.data[2] + ')</li>');
$('#qrcode').attr('src',src);
if (cb)
cb();
*/
});
});
</script>
<title>Example</title>
</head> </head>
<body> <body>
<h1>QR Code:</h1> <h1>QR Code:</h1>
<p>For URL <a href="{{ request.url_root + next_uuid }}">{{ request.url_root + next_uuid }}</a></p> <p>For URL <a href="{{ request.url_root + next_uuid }}">{{ request.url_root + next_uuid }}</a></p>
<img src="{{ qrcode(request.url_root + next_uuid, box_size=12, border=5) }}"> <img id="qrcode" src="{{ qrcode(request.url_root + next_uuid, box_size=12, border=5) }}">
<h1>Last 10 users:</h1> <h1>Last 10 users:</h1>
<li> <!-- div><ul id="log"></ul></div -->
<ul>
{% for hit in hits %} {% for hit in hits %}
<ul>{{ hit['created'] }}, {{ hit['user'] }}</ul> <li>{{ hit['created'] }}, {{ hit['user'] }}</li>
{% endfor %} {% endfor %}
</li> </ul>
</body> </body>
</html> </html>

View File

@ -10,16 +10,19 @@
{% elif error == 'ALREADY_USED' %} {% elif error == 'ALREADY_USED' %}
<h1>Error</h1> <h1>Error</h1>
<p>Code has been used already.</p> <p>Code has been used already.</p>
{% elif error == 'DIFFERENT_NODE' %}
<h1>Error</h1>
<p>Code was not generated by this system.</p>
{% else %} {% else %}
<h1>Thanks</h1> <h1>Thanks</h1>
<p><strong>At {{ time }}</strong>,</p> <p><strong>At {{ time }}</strong>,</p>
<p>Registered (entrance? exit?) for user {{ user }} .</p> <p>Registered entrance or exit for user {{ user }} .</p>
<h2>Last 10 registers for {{ user }}:</h2> <h2>Last 10 registers for {{ user }}:</h2>
<li> <ul>
{% for hit in hits %} {% for hit in hits %}
<ul>{{ hit['created'] }}</ul> <li>{{ hit['created'] }}</li>
{% endfor %} {% endfor %}
</li> </ul>
{% endif %} {% endif %}
</body> </body>
</html> </html>