from flask import Flask, render_template, request, 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 it’s 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 doesn’t 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 overview(): allowed_secrets = session.get('allowed_secrets', []) host = request.host secret_qr_codes = {} secret_folders = {} # 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 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'] else: secret_folders[secret] = [] return render_template('overview.html', allowed_secrets=allowed_secrets, secret_qr_codes=secret_qr_codes, secret_folders=secret_folders)