diff --git a/docker/routlin-dash/app/action_add_account.py b/docker/routlin-dash/app/action_add_account.py index 7756f8e..a6019be 100644 --- a/docker/routlin-dash/app/action_add_account.py +++ b/docker/routlin-dash/app/action_add_account.py @@ -2,12 +2,11 @@ from flask import Blueprint, request, session, redirect, flash import json, re from datetime import datetime, timezone from auth import require_level +from config_utils import ACCOUNTS_FILE import sanitize bp = Blueprint('action_add_account', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' VALID_LEVELS = {'viewer', 'administrator', 'manager'} diff --git a/docker/routlin-dash/app/action_change_password.py b/docker/routlin-dash/app/action_change_password.py index a330f92..571bd95 100644 --- a/docker/routlin-dash/app/action_change_password.py +++ b/docker/routlin-dash/app/action_change_password.py @@ -1,11 +1,10 @@ from flask import Blueprint, request, session, redirect, flash import json, bcrypt from auth import require_level +from config_utils import ACCOUNTS_FILE bp = Blueprint('action_change_password', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' def _load_accounts(): diff --git a/docker/routlin-dash/app/action_clear_ddns_log.py b/docker/routlin-dash/app/action_clear_ddns_log.py index 7149df4..8b52051 100644 --- a/docker/routlin-dash/app/action_clear_ddns_log.py +++ b/docker/routlin-dash/app/action_clear_ddns_log.py @@ -1,9 +1,10 @@ from flask import Blueprint, redirect, flash from auth import require_level +from config_utils import CONFIGS_DIR bp = Blueprint('action_clear_ddns_log', __name__) -LOG_FILE = '/configs/ddns.log' +LOG_FILE = f'{CONFIGS_DIR}/ddns.log' @bp.route('/action/clear_ddns_log', methods=['POST']) diff --git a/docker/routlin-dash/app/action_create_account.py b/docker/routlin-dash/app/action_create_account.py index 1989eb6..a27d1a4 100644 --- a/docker/routlin-dash/app/action_create_account.py +++ b/docker/routlin-dash/app/action_create_account.py @@ -3,13 +3,11 @@ import json, os, bcrypt, secrets, smtplib from datetime import datetime, timezone, timedelta from email.message import EmailMessage from auth import require_level -from config_utils import PRODUCT_DISPLAY_NAME +from config_utils import PRODUCT_DISPLAY_NAME, ACCOUNTS_FILE import sanitize bp = Blueprint('action_create_account', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' CODE_TTL_MIN = 15 diff --git a/docker/routlin-dash/app/action_delete_account.py b/docker/routlin-dash/app/action_delete_account.py index dfb9593..ffde63b 100644 --- a/docker/routlin-dash/app/action_delete_account.py +++ b/docker/routlin-dash/app/action_delete_account.py @@ -1,11 +1,10 @@ from flask import Blueprint, request, session, redirect, flash import json from auth import require_level +from config_utils import ACCOUNTS_FILE bp = Blueprint('action_delete_account', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' def _load_accounts(): diff --git a/docker/routlin-dash/app/action_log_in.py b/docker/routlin-dash/app/action_log_in.py index 957fd31..11e1dec 100644 --- a/docker/routlin-dash/app/action_log_in.py +++ b/docker/routlin-dash/app/action_log_in.py @@ -1,16 +1,16 @@ from flask import Blueprint, request, session, redirect, flash import json, bcrypt from auth import require_level +from config_utils import ACCOUNTS_FILE import sanitize bp = Blueprint('action_log_in', __name__) -DATA_DIR = '/data' def _load_accounts(): try: - with open(f'{DATA_DIR}/authorized_accounts.json') as f: + with open(ACCOUNTS_FILE) as f: return json.load(f) except Exception: return {'accounts': []} diff --git a/docker/routlin-dash/app/action_save_preferences.py b/docker/routlin-dash/app/action_save_preferences.py index 8b32d90..a5856c5 100644 --- a/docker/routlin-dash/app/action_save_preferences.py +++ b/docker/routlin-dash/app/action_save_preferences.py @@ -1,12 +1,11 @@ from flask import Blueprint, request, session, redirect, flash import json from auth import require_level +from config_utils import ACCOUNTS_FILE import sanitize bp = Blueprint('action_save_preferences', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' def _load_accounts(): diff --git a/docker/routlin-dash/app/action_verify_email.py b/docker/routlin-dash/app/action_verify_email.py index 4e84979..d82181d 100644 --- a/docker/routlin-dash/app/action_verify_email.py +++ b/docker/routlin-dash/app/action_verify_email.py @@ -2,11 +2,10 @@ from flask import Blueprint, request, session, redirect, flash import json, os, secrets from datetime import datetime, timezone, timedelta from auth import require_level +from config_utils import ACCOUNTS_FILE bp = Blueprint('action_verify_email', __name__) -DATA_DIR = '/data' -ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' def _load_accounts(): diff --git a/docker/routlin-dash/app/config_utils.py b/docker/routlin-dash/app/config_utils.py index 1293f17..5ea507f 100644 --- a/docker/routlin-dash/app/config_utils.py +++ b/docker/routlin-dash/app/config_utils.py @@ -3,6 +3,8 @@ from datetime import datetime, timezone from flask import session CONFIGS_DIR = '/routlin_location' +DATA_DIR = '/data' +ACCOUNTS_FILE = f'{DATA_DIR}/authorized_accounts.json' CORE_FILE = f'{CONFIGS_DIR}/core.json' DASHBOARD_QUEUE = f'{CONFIGS_DIR}/.dashboard-queue' DASHBOARD_DONE = f'{CONFIGS_DIR}/.dashboard-done' diff --git a/docker/routlin-dash/app/view_page.py b/docker/routlin-dash/app/view_page.py index 1a20c3a..4647b4c 100644 --- a/docker/routlin-dash/app/view_page.py +++ b/docker/routlin-dash/app/view_page.py @@ -5,12 +5,10 @@ import sanitize import validation as validate from datetime import datetime, timezone from zoneinfo import ZoneInfo, ZoneInfoNotFoundError -from config_utils import core_hash, get_pending_entries, get_dashboard_pending, _seconds_until_next_run, _format_timing, _is_locked, _lock_mtime, PRODUCT_DISPLAY_NAME +from config_utils import core_hash, get_pending_entries, get_dashboard_pending, _seconds_until_next_run, _format_timing, _is_locked, _lock_mtime, PRODUCT_DISPLAY_NAME, CONFIGS_DIR, DATA_DIR bp = Blueprint('view_page', __name__) -DATA_DIR = '/data' -CONFIGS_DIR = '/routlin_location' LEVEL_RANK = {'nothing': 0, 'viewer': 1, 'administrator': 2, 'manager': 3} @@ -1485,16 +1483,25 @@ def render_layout(view_id, content_html, tokens): try: import json as _j st = _j.load(open(f'{CONFIGS_DIR}/.status')) + grouped = {'error': [], 'warning': []} for section in ('configurations', 'logs'): for item in st.get(section, []): if item.get('status') == 'problem': sev = item.get('severity', 'error') - cls = 'info-bar-danger' if sev == 'error' else 'info-bar-warning' text = e(item.get('detail', item.get('name', ''))) tip = item.get('suggestion', '') if tip: text += f' {e(tip)}' - problem_bars += f'
\n' + grouped.setdefault(sev, []).append(text) + for sev, items in grouped.items(): + if not items: + continue + cls = 'info-bar-danger' if sev == 'error' else 'info-bar-warning' + if len(items) == 1: + content = items[0] + else: + content = '