diff --git a/.gitignore b/.gitignore index 26464f9..e12ff74 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ /search.db /access_log.db /access_log.db.bak -/folder_permission_config.json +/folder_secret_config.json /folder_mount_config.json /.env /app_config.json diff --git a/analytics.py b/analytics.py index d10d8dc..4d562aa 100644 --- a/analytics.py +++ b/analytics.py @@ -6,6 +6,7 @@ from auth import require_secret from collections import defaultdict import json import os +import auth file_access_temp = [] @@ -189,11 +190,11 @@ def songs_dashboard(): performance_data = [(count, titel) for titel, count in performance_counts.items()] performance_data.sort(reverse=True, key=lambda x: x[0]) - return render_template('songs_dashboard.html', timeframe=timeframe_param, performance_data=performance_data, site=site, category=category) + return render_template('songs_dashboard.html', timeframe=timeframe_param, performance_data=performance_data, site=site, category=category, admin_enabled=auth.is_admin()) @require_secret def connections(): - return render_template('connections.html') + return render_template('connections.html', admin_enabled=auth.is_admin()) @require_secret def dashboard(): @@ -476,7 +477,8 @@ def dashboard(): unique_files=unique_files, unique_user=unique_user, cached_percentage=cached_percentage, - timeframe_data=timeframe_data + timeframe_data=timeframe_data, + admin_enabled=auth.is_admin() ) def export_to_excel(): diff --git a/app.py b/app.py index a9a0e8a..2de3d22 100755 --- a/app.py +++ b/app.py @@ -22,11 +22,12 @@ import base64 import search import auth import analytics as a +import folder_secret_config_editor as fsce with open("app_config.json", 'r') as file: app_config = json.load(file) -with open('folder_permission_config.json') as file: +with open('folder_secret_config.json') as file: folder_config = json.load(file) cache_audio = diskcache.Cache('./filecache_audio', size_limit= app_config['filecache_size_limit_audio'] * 1024**3) @@ -53,6 +54,9 @@ app.add_url_rule('/searchcommand', view_func=search.searchcommand, methods=['POS app.add_url_rule('/songs_dashboard', view_func=a.songs_dashboard) +app.add_url_rule('/admin/folder_secret_config_editor', view_func=auth.require_admin(fsce.folder_secret_config_editor), methods=['GET', 'POST']) +app.add_url_rule('/admin/folder_secret_config_editor/data', view_func=auth.require_admin(fsce.folder_secret_config_data)) +app.add_url_rule('/admin/folder_secret_config_editor/action', view_func=auth.require_admin(fsce.folder_secret_config_action), methods=['POST']) # Grab the HOST_RULE environment variable host_rule = os.getenv("HOST_RULE", "") @@ -548,14 +552,11 @@ def handle_request_initial_data(): def index(path): title_short = app_config.get('TITLE_SHORT', 'Default Title') title_long = app_config.get('TITLE_LONG' , 'Default Title') - admin_enabled = False - if 'admin' in session: - admin_enabled = session['admin'] return render_template("app.html", title_short=title_short, title_long=title_long, - admin_enabled=admin_enabled, + admin_enabled=auth.is_admin() ) if __name__ == '__main__': diff --git a/auth.py b/auth.py index d0ed94c..f207c5b 100644 --- a/auth.py +++ b/auth.py @@ -17,9 +17,24 @@ import hashlib with open("app_config.json", 'r') as file: app_config = json.load(file) -with open('folder_permission_config.json') as file: +with open('folder_secret_config.json') as file: folder_config = json.load(file) +def is_admin(): + """ + Check if the user is an admin based on the session. + """ + return session.get('admin', False) + +def require_admin(f): + @wraps(f) + @require_secret + def decorated_function(*args, **kwargs): + if is_admin(): + return f(*args, **kwargs) + else: + return "You don't have admin permission", 403 + return decorated_function def require_secret(f): @wraps(f) @@ -104,8 +119,10 @@ def require_secret(f): if args_admin and config_admin: if args_admin == config_admin: + print(f"Admin access granted with key: {args_admin}") session['admin'] = True else: + print(f"Admin access denied with key: {args_admin}") session['admin'] = False # 6) If we have folders, proceed; otherwise show index @@ -129,6 +146,7 @@ def require_secret(f): header_text_color=header_text_color, main_text_color=main_text_color, background_color=background_color, + admin_enabled=is_admin() ) return decorated_function @@ -197,7 +215,8 @@ def mylinks(): token_qr_codes=token_qr_codes, token_folders=token_folders, token_url=token_url, - token_valid_to=token_valid_to + token_valid_to=token_valid_to, + admin_enabled=is_admin() ) diff --git a/folder_secret_config_editor.py b/folder_secret_config_editor.py new file mode 100644 index 0000000..de07349 --- /dev/null +++ b/folder_secret_config_editor.py @@ -0,0 +1,63 @@ +from flask import Flask, request, jsonify, render_template +import json +import os +from datetime import datetime +import secrets +import string +import auth + + +DATA_FILE = 'folder_secret_config.json' + +# Secret alphabet +ALPHABET = string.ascii_letters + string.digits + +@auth.require_admin +def load_data(): + with open(DATA_FILE) as f: + try: + data = json.load(f) + print(f"Loaded {len(data)} records from {DATA_FILE}.") + return data + except: + print(f"Error loading {DATA_FILE}. File may be empty or corrupted.") + return [] + +@auth.require_admin +def save_data(data): + with open(DATA_FILE, 'w') as f: + json.dump(data, f, indent=4) + +@auth.require_admin +def folder_secret_config_editor(): + return render_template('folder_secret_config_editor.html', alphabet=ALPHABET, admin_enabled=auth.is_admin()) + +@auth.require_admin +def folder_secret_config_data(): + return jsonify(load_data()) + +@auth.require_admin +def folder_secret_config_action(): + p = request.get_json() + data = load_data() + action = p.get('action') + if action == 'delete': + data = [r for r in data if r['secret'] != p['secret']] + elif action == 'update': + old = p['oldSecret']; new = p['newSecret'] + for i, r in enumerate(data): + if r['secret'] == old: + r['secret'] = new + r['validity'] = datetime.strptime(p['validity'], '%Y-%m-%d').strftime('%d.%m.%Y') + r['folders'] = p['folders'] + break + else: + # append if not found + data.append({ + 'secret': new, + 'validity': datetime.strptime(p['validity'], '%Y-%m-%d').strftime('%d.%m.%Y'), + 'folders': p['folders'] + }) + save_data(data) + return jsonify(success=True) + diff --git a/templates/app.html b/templates/app.html index 767b99e..2838b00 100644 --- a/templates/app.html +++ b/templates/app.html @@ -55,6 +55,11 @@ + {% if admin_enabled %} +
| Timestamp | -Location | -User Agent | -File Path | -File Size | -MIME-Typ | -Cached | -
|---|
| Timestamp | +Location | +User Agent | +File Path | +File Size | +MIME-Typ | +Cached | +
|---|
- Gültig bis: {{ secret_valid_to[secret] }} -
- Link öffnen - -Keine Ordner für dieses Gemeimnis hinterlegt.
- {% endif %} -+ Gültig bis: {{ secret_valid_to[secret] }} +
+ Link öffnen + +Keine Ordner für dieses Gemeimnis hinterlegt.
+ {% endif %}- Gültig bis: {{ token_valid_to[token] }} -
- Link öffnen - -Keine Ordner für dieses Gemeimnis hinterlegt.
- {% endif %} -+ Gültig bis: {{ token_valid_to[token] }} +
+ Link öffnen + +Keine Ordner für dieses Gemeimnis hinterlegt.
+ {% endif %} +