This commit is contained in:
Tim Berchtold 2025-07-05 10:13:28 +02:00
parent eeda5062ae
commit a95e8a00b8
7 changed files with 46 additions and 39 deletions

View file

@ -1,13 +1,13 @@
[DEFAULT] [DEFAULT]
host = 'http://0.0.0.0:5000' host = http://0.0.0.0:5000
max_desks = 8 max_desks = 8
[SETTINGS] [SETTINGS]
lockqrcode_whit_secret = True lockqrcode_whit_secret = True
user = Admin user = Admin
path_json_settings = '/Server/json/availiable-products.json' path_json_settings = ./Server/json/availiable-products.json
[OTHER] [OTHER]
log_diagnose = True log_diagnose = True
first_startup = False first_startup = True

View file

@ -21,7 +21,7 @@ Default has to be changed to your needs:
host -> is where the QR code points to whit secret if enabled. host -> is where the QR code points to whit secret if enabled.
max_desks -> How many desk it shoud create. max_desks -> How many desk it shoud create.
Execute in Terminal the "pip install -r required.txt" to download depending and "python app.py" to run the Flask server and whit it the webserver. Execute in Terminal "python3 -m venv .venv", for the virtual enviroment activate it whit "source .venv/bin/acitvate" (Linux) " or ".venv/Scripts/activate.bat" (Windows) and then "pip install -r required.txt" to download depending and "python app.py" to run the Flask server and whit it the webserver.
## ##

View file

@ -2,9 +2,15 @@
from loguru import logger from loguru import logger
import json import json
import bcrypt import bcrypt
import configparser
from Server.DB.handler import QR, Product, Order, session, User from Server.DB.handler import QR, Product, Order, session, User
config = configparser.ConfigParser()
config.sections()
config.read('Options.ini')
class compare: class compare:
def is_user_pass_valid(username, password): def is_user_pass_valid(username, password):
session_username = session.query(User).filter(User.username == username).one() session_username = session.query(User).filter(User.username == username).one()
@ -102,19 +108,20 @@ class get:
return False return False
''' '''
def valid_products(get_json_=False): def valid_products(get_json_=False):
with open(config['SETTINGS']['path_json_settings'], 'r') as file: global config
#Parse Json Product List with open(config['SETTINGS']['path_json_settings'], 'r') as file:
products = json.load(file) #Parse Json Product List
if get_json_: products = json.load(file)
return products if get_json_:
else: return products
valide_products = [] else:
for category in products.get('products'): valide_products = []
for product in products.get('products').get(category): for category in products.get('products'):
print(product) for product in products.get('products').get(category):
if int(product['quantity']) >= 0: print(product)
valide_products.append(product['name']) if int(product['quantity']) >= 0:
return valide_products valide_products.append(product['name'])
return valide_products
def all_orders(): def all_orders():
# All unfinished orders (finished is False or string "False") # All unfinished orders (finished is False or string "False")

View file

@ -37,7 +37,7 @@ login_manager.init_app(app)
if config['OTHER']['first_startup'] == 'True': if config['OTHER']['first_startup'] == 'True':
print("Please enter a Secure Admin Password:") print("Please enter a Secure Admin Password:")
add._create_user('Admin',input()) add._create_user(config['SETTINGS']['user'],input())
config.set('OTHER', 'first_startup', 'False') config.set('OTHER', 'first_startup', 'False')
with open('Options.ini', 'w') as configfile: with open('Options.ini', 'w') as configfile:
config.write(configfile) config.write(configfile)
@ -112,9 +112,9 @@ def orders(): #TODO on new orderGet refresh orders list
@app.route("/order_get", methods=['GET','POST']) @app.route("/order_get", methods=['GET','POST'])
def order_get(): def order_get():
desk= 1 desk= 1
global config
#POST order #POST order
if request.method == 'POST' and config['SETTINGS']['lockqrcode_whit_secret'] == True: if request.method == 'POST' and config['SETTINGS']['lockqrcode_whit_secret'] == 'True':
ordered_list = [] ordered_list = []
desk = request.form['desk'] desk = request.form['desk']
form = request.form form = request.form
@ -133,18 +133,17 @@ def order_get():
elif request.method == 'GET': elif request.method == 'GET':
desk = int(request.args['desk']) desk = int(request.args['desk'])
secret = int(request.args['secret']) secret = int(request.args['secret'])
try:#TODO FIX! #Feature = True #TODO:Encryption Salting hasing and anti rainbow attack for qr code?? (needed?) if config['SETTINGS']['lockqrcode_whit_secret'] == 'True' and compare.is_QRSecret_valid(desk,secret):
if config['SETTINGS']['lockqrcode_whit_secret'] and compare.is_QRSecret_valid(desk,secret): return render_template('index.html', desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']), orderableItems = get.valid_products(get_json_=True))
return render_template('index.html', desk=desk, MAX_DESKS=config['DEFAULT']['max_desks'], orderableItems = get.valid_products(get_json_=True)) elif config['SETTINGS']['lockqrcode_whit_secret'] == 'False':
elif config['SETTINGS']['lockqrcode_whit_secret'] == False: return render_template('index.html', desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']),orderableItems = get.valid_products(get_json_=True))
return render_template('index.html', desk=desk, MAX_DESKS=config['DEFAULT']['max_desks'],orderableItems = get.valid_products(get_json_=True)) else:
return '<h1>404 wrong Secret?</h1>' #TODO Make the HTML prettier for all return '<h1>Somethign went wrong try again.</h1>' #TODO Make the HTML prettier for all
except: return '<h1>404 wrong Secret?</h1>' #TODO Make the HTML prettier for all
return '<h1>Server/code issue?</h1>' elif config['SETTINGS']['lockqrcode_whit_secret'] == 'True':
elif config['SETTINGS']['lockqrcode_whit_secret'] == True:
return '<h1>your LOCKQRCODE is invalid.</h1>' return '<h1>your LOCKQRCODE is invalid.</h1>'
else: else:
return render_template('index.html',desk=desk, MAX_DESKS=config['DEFAULT']['max_desks'],orderableItems = get.valid_products(get_json_=True)) return render_template('index.html',desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']),orderableItems = get.valid_products(get_json_=True))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.db' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

View file

@ -7,7 +7,8 @@
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body>
<form name="order" onsubmit="return validateForm()" action="{{ url_for('order_get') }}" method="POST" class="flex-container"> <form name="order" onsubmit="return validateForm()" action="{{ url_for('order_get') }}" method="POST" class="flex-container">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<li class="box desk-nr">Tisch Nummer <li class="box desk-nr">Tisch Nummer
<div> <div>
<select name="desk" class="desk-select"> <select name="desk" class="desk-select">

View file

@ -46,10 +46,7 @@
</ul> </ul>
</td> </td>
<td> <td>
<button <button class="finish-btn" onclick="markFinished({{ order[2] }})" id="btn-{{ order[2] }}">
class="finish-btn"
onclick="markFinished({{ order[2] }})"
id="btn-{{ order[2] }}">
Finished Finished
</button> </button>
</td> </td>
@ -59,15 +56,17 @@
<tr><td colspan="3">No open orders.</td></tr> <tr><td colspan="3">No open orders.</td></tr>
{% endfor %} {% endfor %}
</table> </table>
<script> <script>
var csrfToken = "{{ csrf_token() }}";
// Track active timers for each order // Track active timers for each order
window.activeTimers = {}; window.activeTimers = {};
function markFinished(orderId) { function markFinished(orderId) {
fetch('/orders', { fetch('/orders', {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': csrfToken },
body: `order_id=${orderId}&action=finish` body: `order_id=${orderId}&action=finish`
}) })
.then(response => response.json()) .then(response => response.json())
@ -106,7 +105,8 @@
fetch('/orders', { fetch('/orders', {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' ,
'X-CSRFToken': csrfToken },
body: `order_id=${orderId}&action=undo` body: `order_id=${orderId}&action=undo`
}) })
.then(response => response.json()) .then(response => response.json())

2
app.py
View file

@ -20,7 +20,7 @@ you want async logging.
def run(): #TODO: sys.stderr back to a file log?? def run(): #TODO: sys.stderr back to a file log??
logger.add(sys.stderr, format="{time} {level} {message}", filter="startup", level="INFO") logger.add(sys.stderr, format="{time} {level} {message}", filter="startup", level="INFO")
logger.add(sys.stderr, backtrace=True, diagnose=config['OTHER']['log_diagnose']) logger.add(sys.stderr, backtrace=True, diagnose=config['OTHER']['log_diagnose'])
app.run(debug=True) app.run(debug=False)
if __name__ == "__main__": if __name__ == "__main__":
#First startup is handled in DB/handler #First startup is handled in DB/handler