Adds hash to URL and effects to new content. Avoids page refresh
This commit is contained in:
parent
c49192a6d7
commit
6e88c25339
69
main.py
69
main.py
@ -6,8 +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
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO, emit
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
|
||||||
# WIP: use sockets to broadcast when a hit to the expected uuid has been
|
# 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
|
||||||
@ -16,7 +18,8 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
FlaskUUID(app)
|
FlaskUUID(app)
|
||||||
QRcode(app)
|
#QRcode(app)
|
||||||
|
qrcode = QRcode(app)
|
||||||
app.config['SECRET_KEY'] = '53a8373e7ae652cd38beba15454b1dc4'
|
app.config['SECRET_KEY'] = '53a8373e7ae652cd38beba15454b1dc4'
|
||||||
#app = ProxyFix(app, x_for=1, x_host=1)
|
#app = ProxyFix(app, x_for=1, x_host=1)
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||||
@ -27,23 +30,28 @@ def get_db_connection():
|
|||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
def hash_string(string):
|
||||||
|
salt = 'xpwQDFQ7gvcQ--rgO7l9yA'
|
||||||
|
return hashlib.md5(salt.encode() + string.encode()).hexdigest()
|
||||||
|
|
||||||
|
def check_hash(string, hashed_string):
|
||||||
|
salt = 'xpwQDFQ7gvcQ--rgO7l9yA'
|
||||||
|
return hashed_string == hashlib.md5(salt.encode() + string.encode()).hexdigest()
|
||||||
|
|
||||||
|
def generate_next_url():
|
||||||
|
next_uuid = str(uuid.uuid1())
|
||||||
|
url = request.url_root + str(next_uuid) + '/' + hash_string(next_uuid)
|
||||||
|
return url
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def show_qr_and_list():
|
def show_qr_and_list():
|
||||||
# TODO: reject direct connections to server; allow access only via proxy
|
# 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: store next_uuid in a queue, and remove it once it's used. Accept only ids
|
return render_template("template.html")
|
||||||
# from the queue
|
|
||||||
next_uuid = uuid.uuid1()
|
|
||||||
return render_template("template.html",
|
|
||||||
next_uuid=str(next_uuid),
|
|
||||||
hits=data)
|
|
||||||
|
|
||||||
@app.route('/<uuid:id>')
|
@app.route('/<uuid:id>/<hashed>')
|
||||||
def catch_uuids(id):
|
def catch_uuids(id, hashed):
|
||||||
ua = request.headers.get('Remote-User')
|
user = request.headers.get('Remote-User')
|
||||||
# TODO: Check directly with Authelia using https://auth.agofer.net/api/verify
|
# TODO: Check directly with Authelia using https://auth.agofer.net/api/verify
|
||||||
time = datetime.now().strftime("%A %Y-%m-%d %H:%M:%S")
|
time = datetime.now().strftime("%A %Y-%m-%d %H:%M:%S")
|
||||||
error = None
|
error = None
|
||||||
@ -51,31 +59,44 @@ 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()
|
||||||
if not ua:
|
if not user:
|
||||||
error = 'NO_USERNAME'
|
error = 'NO_USERNAME'
|
||||||
elif id.fields[5] != uuid.getnode():
|
|
||||||
error = 'DIFFERENT_NODE'
|
|
||||||
elif existing:
|
elif existing:
|
||||||
error = 'ALREADY_USED'
|
error = 'ALREADY_USED'
|
||||||
|
elif not check_hash(str(id), str(hashed)):
|
||||||
|
error = 'DIFFERENT_NODE'
|
||||||
else:
|
else:
|
||||||
conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua))
|
conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), user))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
socketio.emit('qr_used', {'data': (time, ua, str(id))})
|
#socketio.emit('qr_used', {'data': (time, user, str(id))})
|
||||||
|
url = generate_next_url()
|
||||||
|
qr = qrcode(url)
|
||||||
|
socketio.emit('qr_used', {'data': (qr, url, user, time)})
|
||||||
|
|
||||||
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', (user,)
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return render_template('thanks.html', user=ua, time=time, error=error, hits=data)
|
return render_template('thanks.html', user=user, time=time, error=error, hits=data)
|
||||||
|
|
||||||
@socketio.on('message')
|
@socketio.on('message')
|
||||||
def handle_message(data):
|
def handle_message(data):
|
||||||
print('received message: ' + data)
|
print('received message: ' + data)
|
||||||
|
|
||||||
@socketio.on('my_event')
|
@socketio.on('connection')
|
||||||
def handle_my_custom_event(json):
|
def handle_initial_connection(json_data):
|
||||||
print('received json: ' + str(json))
|
url = generate_next_url()
|
||||||
|
qr = qrcode(url)
|
||||||
|
conn = get_db_connection()
|
||||||
|
last_entries = conn.execute('SELECT user, created FROM hits ORDER BY id DESC LIMIT 10')
|
||||||
|
array_entries = []
|
||||||
|
for entry in last_entries:
|
||||||
|
array_entries.append((entry[0], entry[1]))
|
||||||
|
conn.close()
|
||||||
|
emit('initial_qr', {'data': (qr, url, array_entries)})
|
||||||
|
#socketio.emit('initial_qr', {'data': (qr,)})
|
||||||
|
print('received json: ' + str(json_data))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
#app.run(host='0.0.0.0')
|
#app.run(host='0.0.0.0')
|
||||||
|
|||||||
BIN
static/loading.gif
Normal file
BIN
static/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@ -7,16 +7,32 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var socket = io();
|
var socket = io();
|
||||||
socket.on('connect', function() {
|
socket.on('connect', function() {
|
||||||
socket.emit('my_event', {data: 'Connected to server'});
|
socket.emit('connection', {data: 'Connected to server'});
|
||||||
});
|
});
|
||||||
socket.on('qr_used', function(msg, cb) {
|
socket.on('initial_qr', function(msg, cb) {
|
||||||
location.reload(true);
|
$('#qrcode').prop('src', msg.data[0]);
|
||||||
/*
|
$('#url').prop('href', msg.data[1]).text(msg.data[1]);
|
||||||
$('#log').append('<li>' + msg.data[0] + ': ' + msg.data[1] + ' (' + msg.data[2] + ')</li>');
|
$('#log').empty();
|
||||||
$('#qrcode').attr('src',src);
|
msg.data[2].forEach(function(item) {
|
||||||
|
$('#log').append('<li>' + item[0] + ': ' + item[1] + '</li>');
|
||||||
|
}
|
||||||
|
);
|
||||||
if (cb)
|
if (cb)
|
||||||
cb();
|
cb();
|
||||||
|
});
|
||||||
|
socket.on('qr_used', function(msg, cb) {
|
||||||
|
/*
|
||||||
|
location.reload(true);
|
||||||
*/
|
*/
|
||||||
|
$('#qrcode').prop('src', msg.data[0]).fadeTo('fast', 0.05, function(){$(this).delay(100).fadeTo('slow', 1)});
|
||||||
|
$('#url').prop('href', msg.data[1]).text(msg.data[1]);
|
||||||
|
//$('#log').fadeIn(500, function() { $(this).prepend('<li>' + msg.data[2] + ': ' + msg.data[3] + '</li>') });
|
||||||
|
var new_entry = '<li>' + msg.data[2] + ': ' + msg.data[3] + '</li>';
|
||||||
|
$(new_entry).hide().prependTo('#log').fadeIn('slow');
|
||||||
|
$('#log').fadeIn(500, function() { $(this).prepend() });
|
||||||
|
$('#log li:gt(9)' ).remove();
|
||||||
|
if (cb)
|
||||||
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -24,15 +40,21 @@
|
|||||||
</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 id="qrcode" 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) }}">
|
||||||
|
#}
|
||||||
|
<p>For URL <a id="url" href="/">__loading...__</a></p>
|
||||||
|
<img id="qrcode" src="/static/loading.gif">
|
||||||
<h1>Last 10 users:</h1>
|
<h1>Last 10 users:</h1>
|
||||||
<!-- div><ul id="log"></ul></div -->
|
<div><ul id="log"></ul></div>
|
||||||
|
{#
|
||||||
<ul>
|
<ul>
|
||||||
{% for hit in hits %}
|
{% for hit in hits %}
|
||||||
<li>{{ hit['created'] }}, {{ hit['user'] }}</li>
|
<li>{{ hit['created'] }}, {{ hit['user'] }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
#}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user