diff --git a/app.py b/app.py index a3756c9..e5a1879 100755 --- a/app.py +++ b/app.py @@ -352,7 +352,7 @@ def serve_file(subpath): try: full_path = check_path(full_path) except (ValueError, PermissionError) as e: - return jsonify({'error': str(e)}), 403 + return jsonify({'Unauthorized': str(e)}), 403 if not os.path.isfile(full_path): app.logger.error(f"File not found: {full_path}") @@ -511,9 +511,9 @@ def get_transcript(subpath): return content, 200, {'Content-Type': 'text/markdown; charset=utf-8'} -@app.route("/create_share/") +@app.route("/create_token/") @auth.require_secret -def create_share(subpath): +def create_token(subpath): scheme = request.scheme # current scheme (http or https) host = request.host if 'admin' not in session and not session.get('admin'): @@ -541,7 +541,7 @@ def create_share(subpath): ] } - token = auth.generate_secret_key_compressed(data) + token = auth.generate_token(data) url = f"{scheme}://{host}?token={token}" qr = qrcode.QRCode(version=1, box_size=10, border=4) @@ -552,7 +552,7 @@ def create_share(subpath): img.save(buffer, format="PNG") buffer.seek(0) img_base64 = base64.b64encode(buffer.getvalue()).decode('ascii') - token_item = auth.decode_secret_key_compressed(token) + token_item = auth.decode_token(token) return render_template('view_token.html', token_qr_code=img_base64, @@ -562,6 +562,40 @@ def create_share(subpath): ) +@app.route("/create_dl_token/") +@auth.require_secret +def create_dl_token(subpath): + scheme = request.scheme # current scheme (http or https) + host = request.host + print(f"Creating download token for subpath: {subpath}") + # 1) Locate the real file on disk + root, *relative_parts = subpath.split('/') + base_path = session['folders'].get(root) + full_path = os.path.join(base_path or '', *relative_parts) + + try: + full_path = check_path(full_path) + print(f"Full path after check: {full_path}") + except (ValueError, PermissionError) as e: + return jsonify({'Unauthorized': str(e)}), 403 + + if not os.path.isfile(full_path): + app.logger.error(f"File not found: {full_path}") + return "File not found", 404 + + validity_date = (datetime.now() + timedelta(days=1)).strftime('%d.%m.%Y') + data = { + "validity": validity_date, + "filename": full_path + } + + token = auth.generate_token(data) + + url = f"{scheme}://{host}?dl_token={token}" + + return url + + def query_recent_connections(): global clients_connected, background_thread_running background_thread_running = True diff --git a/auth.py b/auth.py index 72c2cca..1be5b34 100644 --- a/auth.py +++ b/auth.py @@ -123,7 +123,7 @@ def require_secret(f): session['folders'][folder_info['foldername']] = folder_info['folderpath'] for token_in_session in session.get('valid_tokens', []): - token_item = decode_secret_key_compressed(token_in_session) + token_item = decode_token(token_in_session) for folder_info in token_item['folders']: session['folders'][folder_info['foldername']] = folder_info['folderpath'] @@ -230,7 +230,7 @@ def mylinks(): img_base64 = base64.b64encode(buffer.getvalue()).decode('ascii') token_qr_codes[token] = img_base64 - token_item = decode_secret_key_compressed(token) + token_item = decode_token(token) token_folders[token] = token_item.get('folders') token_url[token] = url token_valid_to[token] = token_item.get('validity', 'Unbekannt') @@ -279,14 +279,14 @@ def is_valid_token(secret_key: str, hmac_length: int = 32) -> bool: date has not yet passed. Returns True if: - - signature matches (via decode_secret_key_compressed) + - signature matches (via decode_token) - the payload contains a "validity" field in DD.MM.YYYY format - today's date <= validity date Otherwise returns False. """ try: - payload = decode_secret_key_compressed(secret_key, hmac_length) + payload = decode_token(secret_key, hmac_length) except ValueError: return False @@ -326,7 +326,7 @@ def _shorten_keys(obj: Any, mapping: Dict[str,str]) -> Any: else: return obj -def generate_secret_key_compressed( +def generate_token( payload: dict, hmac_length: int = 32 ) -> str: @@ -364,12 +364,12 @@ def generate_secret_key_compressed( return f"{encoded}{signature}{length_hex}" -def decode_secret_key_compressed( +def decode_token( secret_key: str, hmac_length: int = 32 ) -> dict: """ - Reverse of generate_secret_key_compressed: + Reverse of generate_token: - verify signature (using same hmac_length) - base64-decode → zlib-decompress → JSON - restore original keys @@ -431,8 +431,8 @@ if __name__ == '__main__': ] } - token = generate_secret_key_compressed(payload) + token = generate_token(payload) print("Token:", token) - result = decode_secret_key_compressed(token) + result = decode_token(token) print("Decoded payload:", result) \ No newline at end of file diff --git a/static/app.js b/static/app.js index af89095..ca73ca0 100644 --- a/static/app.js +++ b/static/app.js @@ -364,11 +364,11 @@ document.querySelectorAll('.play-file').forEach(link => { }); }); - // create share icon clicks. + // create token icon clicks. document.querySelectorAll('.create-share').forEach(link => { link.addEventListener('click', function (event) { event.preventDefault(); - const url = '/create_share/' + this.getAttribute('data-url'); + const url = '/create_token/' + this.getAttribute('data-url'); console.log(url); fetch(url) .then(response => {