diff --git a/docker/routlin-dash/app/action_apply_ddns_ip_check.py b/docker/routlin-dash/app/action_apply_ddns_ip_check.py deleted file mode 100644 index 2bfdc53..0000000 --- a/docker/routlin-dash/app/action_apply_ddns_ip_check.py +++ /dev/null @@ -1,31 +0,0 @@ -from flask import Blueprint, request, redirect, flash -from auth import require_level -from config_utils import load_core, save_core, verify_core_hash - -bp = Blueprint('action_apply_ddns_ip_check', __name__) - -VIEW = '/view/view_ddns' - - -@bp.route('/action/ddns_ip_check_save', methods=['POST']) -@require_level('administrator') -def ddns_ip_check_save(): - if not verify_core_hash(request.form.get('config_hash', '')): - flash('Configuration was modified by another session. Please refresh and try again.', 'error') - return redirect(VIEW) - - http_services = [u.strip() for u in request.form.getlist('http_services') if u.strip()] - dig_services = [u.strip() for u in request.form.getlist('dig_services') if u.strip()] - - if not http_services and not dig_services: - flash('At least one IP check service is required.', 'error') - return redirect(VIEW) - - services = [{'type': 'http', 'url': u} for u in http_services] - services += [{'type': 'dig', 'url': u} for u in dig_services] - - core = load_core() - core.setdefault('ddns', {})['ip_check_services'] = services - save_core(core) - flash('IP check services saved.', 'success') - return redirect(VIEW) diff --git a/docker/routlin-dash/app/action_clear_ddns_log.py b/docker/routlin-dash/app/action_clear_ddns_log.py deleted file mode 100644 index f3144a1..0000000 --- a/docker/routlin-dash/app/action_clear_ddns_log.py +++ /dev/null @@ -1,27 +0,0 @@ -import os -from flask import Blueprint, redirect, flash, send_file, abort -from auth import require_level -from config_utils import CONFIGS_DIR - -bp = Blueprint('action_clear_ddns_log', __name__) - -LOG_FILE = f'{CONFIGS_DIR}/ddns.log' - - -@bp.route('/action/clear_ddns_log', methods=['POST']) -@require_level('administrator') -def clear_ddns_log(): - try: - open(LOG_FILE, 'w').close() - flash('DDNS log cleared.', 'success') - except Exception as ex: - flash(f'Could not clear log: {ex}', 'error') - return redirect('/view/view_ddns') - - -@bp.route('/action/download_ddns_log', methods=['GET']) -@require_level('administrator') -def download_ddns_log(): - if not os.path.isfile(LOG_FILE): - abort(404) - return send_file(LOG_FILE, as_attachment=True, download_name='ddns.log', mimetype='text/plain') diff --git a/docker/routlin-dash/app/action_apply_ddns_providers.py b/docker/routlin-dash/app/action_ddns.py similarity index 68% rename from docker/routlin-dash/app/action_apply_ddns_providers.py rename to docker/routlin-dash/app/action_ddns.py index 5e03fd9..12459eb 100644 --- a/docker/routlin-dash/app/action_apply_ddns_providers.py +++ b/docker/routlin-dash/app/action_ddns.py @@ -1,18 +1,20 @@ +import os import re -from flask import Blueprint, request, redirect, flash +from flask import Blueprint, request, redirect, flash, send_file, abort from auth import require_level -from config_utils import load_core, save_core, verify_core_hash, queued_msg +from config_utils import load_core, save_core, verify_core_hash, queued_msg, CONFIGS_DIR import sanitize import validation as validate -bp = Blueprint('action_apply_ddns_providers', __name__) +bp = Blueprint('action_ddns', __name__) -VIEW = '/view/view_ddns' +VIEW = '/view/view_ddns' +LOG_FILE = f'{CONFIGS_DIR}/ddns.log' -@bp.route('/action/add_ddns_provider', methods=['POST']) +@bp.route('/action/ddns_cardaddaccount_add', methods=['POST']) @require_level('administrator') -def add_ddns_provider(): +def ddns_cardaddaccount_add(): provider_type = sanitize.filtervalue(request.form.get('provider', ''), validate.VALID_DDNS_PROVIDERS) description = sanitize.description(request.form.get('description', '')) hostnames = sanitize.domainlist(request.form.get('hostnames', '').splitlines()) @@ -46,9 +48,9 @@ def add_ddns_provider(): return redirect(VIEW) -@bp.route('/action/edit_ddns_provider', methods=['POST']) +@bp.route('/action/ddns_tableaccounts_rowedit', methods=['POST']) @require_level('administrator') -def edit_ddns_provider(): +def ddns_tableaccounts_rowedit(): try: row_index = int(request.form.get('row_index', -1)) except (TypeError, ValueError): @@ -88,30 +90,30 @@ def edit_ddns_provider(): return redirect(VIEW) -@bp.route('/action/ddns_cardlog_save', methods=['POST']) +@bp.route('/action/ddns_tableaccounts_rowdelete', methods=['POST']) @require_level('administrator') -def ddns_cardlog_save(): - log_max_kb = validate.int_range(request.form.get('log_max_kb', '').strip(), 64, None) - if log_max_kb is None: - flash('Max Log Size must be a number >= 64.', 'error') +def ddns_tableaccounts_rowdelete(): + try: + row_index = int(request.form.get('row_index', -1)) + except (TypeError, ValueError): + flash('Invalid row index.', 'error') return redirect(VIEW) - log_errors_only = 'log_errors_only' in request.form - if not verify_core_hash(request.form.get('config_hash', '')): - flash('Configuration was modified by another session. Please refresh and try again.', 'error') + + core = load_core() + providers = core.setdefault('ddns', {}).setdefault('providers', []) + if row_index < 0 or row_index >= len(providers): + flash('Invalid provider index.', 'error') return redirect(VIEW) - core = load_core() - core.setdefault('ddns', {}).setdefault('general', {}).update({ - 'log_max_kb': log_max_kb, - 'log_errors_only': log_errors_only, - }) + + del providers[row_index] save_core(core) - flash('DDNS log settings saved.', 'success') + flash('DDNS provider deleted.', 'success') return redirect(VIEW) -@bp.route('/action/ddns_cardinterval_save', methods=['POST']) +@bp.route('/action/ddns_cardcheckinterval_save', methods=['POST']) @require_level('administrator') -def ddns_cardinterval_save(): +def ddns_cardcheckinterval_save(): raw = request.form.get('timer_interval', '').strip() try: mins = int(raw) @@ -131,22 +133,65 @@ def ddns_cardinterval_save(): return redirect(VIEW) -@bp.route('/action/delete_ddns_provider', methods=['POST']) +@bp.route('/action/ddns_cardipcheckservices_save', methods=['POST']) @require_level('administrator') -def delete_ddns_provider(): - try: - row_index = int(request.form.get('row_index', -1)) - except (TypeError, ValueError): - flash('Invalid row index.', 'error') +def ddns_cardipcheckservices_save(): + if not verify_core_hash(request.form.get('config_hash', '')): + flash('Configuration was modified by another session. Please refresh and try again.', 'error') return redirect(VIEW) - core = load_core() - providers = core.setdefault('ddns', {}).setdefault('providers', []) - if row_index < 0 or row_index >= len(providers): - flash('Invalid provider index.', 'error') + http_services = [u.strip() for u in request.form.getlist('http_services') if u.strip()] + dig_services = [u.strip() for u in request.form.getlist('dig_services') if u.strip()] + + if not http_services and not dig_services: + flash('At least one IP check service is required.', 'error') return redirect(VIEW) - del providers[row_index] + services = [{'type': 'http', 'url': u} for u in http_services] + services += [{'type': 'dig', 'url': u} for u in dig_services] + + core = load_core() + core.setdefault('ddns', {})['ip_check_services'] = services save_core(core) - flash('DDNS provider deleted.', 'success') + flash('IP check services saved.', 'success') return redirect(VIEW) + + +@bp.route('/action/ddns_cardddnslog_save', methods=['POST']) +@require_level('administrator') +def ddns_cardddnslog_save(): + log_max_kb = validate.int_range(request.form.get('log_max_kb', '').strip(), 64, None) + if log_max_kb is None: + flash('Max Log Size must be a number >= 64.', 'error') + return redirect(VIEW) + log_errors_only = 'log_errors_only' in request.form + if not verify_core_hash(request.form.get('config_hash', '')): + flash('Configuration was modified by another session. Please refresh and try again.', 'error') + return redirect(VIEW) + core = load_core() + core.setdefault('ddns', {}).setdefault('general', {}).update({ + 'log_max_kb': log_max_kb, + 'log_errors_only': log_errors_only, + }) + save_core(core) + flash('DDNS log settings saved.', 'success') + return redirect(VIEW) + + +@bp.route('/action/ddns_cardddnslog_clear', methods=['POST']) +@require_level('administrator') +def ddns_cardddnslog_clear(): + try: + open(LOG_FILE, 'w').close() + flash('DDNS log cleared.', 'success') + except Exception as ex: + flash(f'Could not clear log: {ex}', 'error') + return redirect(VIEW) + + +@bp.route('/action/ddns_cardddnslog_download', methods=['GET']) +@require_level('administrator') +def ddns_cardddnslog_download(): + if not os.path.isfile(LOG_FILE): + abort(404) + return send_file(LOG_FILE, as_attachment=True, download_name='ddns.log', mimetype='text/plain') diff --git a/docker/routlin-dash/app/action_dnsblocklists.py b/docker/routlin-dash/app/action_dnsblocklists.py index 03117cf..9da3097 100644 --- a/docker/routlin-dash/app/action_dnsblocklists.py +++ b/docker/routlin-dash/app/action_dnsblocklists.py @@ -79,9 +79,9 @@ def dnsblocklists_tableblocklists_rowdelete(): return redirect(VIEW) -@bp.route('/action/dnsblocklists_tableblocklist_rowedit', methods=['POST']) +@bp.route('/action/dnsblocklists_tableblocklists_rowedit', methods=['POST']) @require_level('administrator') -def dnsblocklists_tableblocklist_rowedit(): +def dnsblocklists_tableblocklists_rowedit(): idx = _row_index() if idx is None: flash('Invalid request.', 'error') diff --git a/docker/routlin-dash/app/main.py b/docker/routlin-dash/app/main.py index 7ade6cb..6dd3c72 100644 --- a/docker/routlin-dash/app/main.py +++ b/docker/routlin-dash/app/main.py @@ -21,9 +21,7 @@ from action_add_account import bp as action_add_account_bp from action_delete_account import bp as action_delete_account_bp from action_save_preferences import bp as action_save_preferences_bp from action_change_password import bp as action_change_password_bp -from action_clear_ddns_log import bp as action_clear_ddns_log_bp -from action_apply_ddns_providers import bp as action_apply_ddns_providers_bp -from action_apply_ddns_ip_check import bp as action_apply_ddns_ip_check_bp +from action_ddns import bp as action_ddns_bp from api_apply_status import bp as api_apply_status_bp app = Flask(__name__) @@ -49,9 +47,7 @@ app.register_blueprint(action_add_account_bp) app.register_blueprint(action_delete_account_bp) app.register_blueprint(action_save_preferences_bp) app.register_blueprint(action_change_password_bp) -app.register_blueprint(action_clear_ddns_log_bp) -app.register_blueprint(action_apply_ddns_providers_bp) -app.register_blueprint(action_apply_ddns_ip_check_bp) +app.register_blueprint(action_ddns_bp) app.register_blueprint(api_apply_status_bp) def _seed_initial_account(): diff --git a/docker/routlin-dash/data/page_content.json b/docker/routlin-dash/data/page_content.json index b834740..fe96d8b 100644 --- a/docker/routlin-dash/data/page_content.json +++ b/docker/routlin-dash/data/page_content.json @@ -320,7 +320,7 @@ "label": "Check Interval", "value": "%DDNS_TIMER_INTERVAL%", "sub": "%STAT_PUBLIC_IP_LAST_CHECKED%", - "edit_action": "/action/ddns_cardinterval_save", + "edit_action": "/action/ddns_cardcheckinterval_save", "edit_field": "timer_interval", "edit_input_type": "number", "edit_min": "1", @@ -345,7 +345,7 @@ "items": [ { "type": "form", - "action": "/action/ddns_ip_check_save", + "action": "/action/ddns_cardipcheckservices_save", "method": "post", "items": [ { @@ -369,7 +369,7 @@ "items": [ { "type": "button_primary", - "action": "/action/ddns_ip_check_save", + "action": "/action/ddns_cardipcheckservices_save", "method": "post", "text": "Save" }, @@ -416,7 +416,7 @@ "row_actions": [ { "client_requirement": "client_is_administrator+", - "action": "/action/edit_ddns_provider", + "action": "/action/ddns_tableaccounts_rowedit", "method": "inline_edit", "text": "Edit", "class": "btn-ghost btn-sm", @@ -446,7 +446,7 @@ }, { "client_requirement": "client_is_administrator+", - "action": "/action/delete_ddns_provider", + "action": "/action/ddns_tableaccounts_rowdelete", "method": "post", "text": "Delete", "class": "btn-danger btn-sm" @@ -460,7 +460,7 @@ "items": [ { "type": "form", - "action": "/action/add_ddns_provider", + "action": "/action/ddns_cardaddaccount_add", "method": "post", "items": [ { @@ -493,7 +493,7 @@ "items": [ { "type": "button_primary", - "action": "/action/add_ddns_provider", + "action": "/action/ddns_cardaddaccount_add", "method": "post", "text": "Add Provider" }, @@ -527,12 +527,12 @@ "items": [ { "type": "button_ghost", - "action": "/action/download_ddns_log", + "action": "/action/ddns_cardddnslog_download", "text": "Download Log" }, { "type": "button_danger", - "action": "/action/clear_ddns_log", + "action": "/action/ddns_cardddnslog_clear", "method": "post", "text": "Clear Log" } @@ -543,7 +543,7 @@ }, { "type": "form", - "action": "/action/ddns_cardlog_save", + "action": "/action/ddns_cardddnslog_save", "method": "post", "items": [ { @@ -568,7 +568,7 @@ "items": [ { "type": "button_primary", - "action": "/action/ddns_cardlog_save", + "action": "/action/ddns_cardddnslog_save", "method": "post", "text": "Save" }, @@ -1234,7 +1234,7 @@ "row_actions": [ { "client_requirement": "client_is_administrator+", - "action": "/action/dnsblocklists_tableblocklist_rowedit", + "action": "/action/dnsblocklists_tableblocklists_rowedit", "method": "inline_edit", "text": "Edit", "class": "btn-ghost btn-sm",