bethaus-app/auth.py
2025-03-23 15:41:45 +01:00

130 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from flask import Flask, render_template, request, redirect, url_for, session
from functools import wraps
from datetime import datetime, date, timedelta
import io
import json
import qrcode
import base64
folder_config = {}
def require_secret(f):
@wraps(f)
def decorated_function(*args, **kwargs):
global folder_config
if not folder_config:
with open('folder_config.json') as file:
folder_config = json.load(file)
def is_valid(config_item, provided_secret):
"""
Checks if today's date is <= validity date
AND if the provided secret matches config_item['secret'].
"""
folder_validity = config_item['validity']
# Convert string to a date if necessary:
if isinstance(folder_validity, str):
folder_validity = datetime.strptime(folder_validity, '%d.%m.%Y').date()
# Return whether it's still valid and secrets match:
return (
date.today() <= folder_validity and
provided_secret == config_item['secret']
)
# 1) Get secret from query params (if any)
args_secret = request.args.get('secret')
# 2) Initialize 'allowed_secrets' in the session if missing
if 'allowed_secrets' not in session:
session['allowed_secrets'] = []
# 3) If a new secret is provided, check if its valid, and add to session if so
if args_secret:
for config_item in folder_config:
if is_valid(config_item, args_secret):
if args_secret not in session['allowed_secrets']:
session['allowed_secrets'].append(args_secret)
session.permanent = True # Make the session permanent
# 4) Re-check validity of each secret in session['allowed_secrets']
# If a secret is no longer valid (or not in config), remove it.
for secret_in_session in session['allowed_secrets'][:]:
# Find the current config item with matching secret
config_item = next(
(c for c in folder_config if c['secret'] == secret_in_session),
None
)
# If the config item doesnt exist or is invalid, remove secret
if config_item is None or not is_valid(config_item, secret_in_session):
session['allowed_secrets'].remove(secret_in_session)
# 5) Build session['folders'] fresh from the valid secrets
session['folders'] = {}
for secret_in_session in session.get('allowed_secrets', []):
config_item = next(
(c for c in folder_config if c['secret'] == secret_in_session),
None
)
if config_item:
for folder_info in config_item['folders']:
session['folders'][folder_info['foldername']] = folder_info['folderpath']
# 6) If we have folders, proceed; otherwise show index
if session['folders']:
return f(*args, **kwargs)
else:
return render_template('index.html')
return decorated_function
@require_secret
def mylinks():
allowed_secrets = session.get('allowed_secrets', [])
host = request.host
secret_qr_codes = {}
secret_folders = {}
secret_valid_to = {}
# Build a QR code for each secret (using the URL with the secret as query parameter)
for secret in allowed_secrets:
url = f"https://{host}?secret={secret}"
qr = qrcode.QRCode(version=1, box_size=10, border=4)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buffer = io.BytesIO()
img.save(buffer, format="PNG")
buffer.seek(0)
img_base64 = base64.b64encode(buffer.getvalue()).decode('ascii')
secret_qr_codes[secret] = img_base64
# Lookup folder info and valid-to date for this secret from the global folder_config.
config_item = next((c for c in folder_config if c['secret'] == secret), None)
if config_item:
secret_folders[secret] = config_item['folders']
secret_valid_to[secret] = config_item.get('validity', 'Unbekannt')
else:
secret_folders[secret] = []
secret_valid_to[secret] = 'Unbekannt'
return render_template('mylinks.html',
allowed_secrets=allowed_secrets,
secret_qr_codes=secret_qr_codes,
secret_folders=secret_folders,
secret_valid_to=secret_valid_to)
def remove_secret():
secret_to_remove = request.form.get('secret')
allowed_secrets = session.get('allowed_secrets', [])
if secret_to_remove in allowed_secrets:
allowed_secrets.remove(secret_to_remove)
session['allowed_secrets'] = allowed_secrets
return redirect(url_for('mylinks'))
return render_template('mylinks.html',
allowed_secrets=allowed_secrets,
secret_qr_codes=secret_qr_codes,
secret_folders=secret_folders)