diff --git a/helper.py b/helper.py index 54712f2..dc1ff00 100644 --- a/helper.py +++ b/helper.py @@ -1,5 +1,5 @@ -import logging, sys, pytz, os, headscale +import logging, sys, pytz, os, headscale, requests from datetime import datetime, timedelta, date from dateutil import parser @@ -84,4 +84,82 @@ def get_color(id, type = ""): "grey lighten-1", ] index = id % len(colors) - return colors[index] \ No newline at end of file + return colors[index] + +def error_message_format(type, title, message): + content = """ + + """ + return content + +def startup_checks(): + url = headscale.get_url() + + # Return an error message if things fail. + # Return a formatted error message for EACH fail. + # Otherwise, return "Pass" + pass = True + + # Check 1: See if the Headscale server is reachable: + reachable = NULL + response = requests.delete( + str(url)+"/api/v1/, + headers={ + 'Accept': 'application/json', + 'Authorization': 'Bearer '+str(api_key) + } + ) + if response.status_code == 200: + reachable = True + else: + reachable = False + pass = False + + # Check 2: See if /data/ is writable: + writable = NULL + try: + key_file = open("/data/key.txt", "wb+") + writable = True + except PermissionError: + writable = False + pass = False + + if pass: return "Pass" + + messageHTML = "" + # Generate the message: + if not reachable: + message = """ +

Your headscale server is either unreachable or not properly configured. + Please ensure your configuration is correct (Check for 200 status on + """+url+"""/api/v1 failed.)

+ """ + messageHTML += format_error_message("Error", "Headscale unreachable", message) + if not writable: + message = """ +

/data/key.txt is not writable. Please ensure your + permissions are correct. /data mount should be writable + by UID/GID 1000:1000

+ """ + messageHTML += format_error_message("Error", "/data not writable", message) + return messageHTML \ No newline at end of file diff --git a/server.py b/server.py index 7c51d75..5f84eb9 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,5 @@ import requests, json, renderer, headscale, helper, logging, sys, pytz, os, time -from flask import Flask, render_template, request, url_for, redirect +from flask import Flask, render_template, request, url_for, redirect, Markup from datetime import datetime, timedelta, date from dateutil import parser @@ -47,6 +47,8 @@ app.logger.debug("BASE_PATH: "+BASE_PATH) def overview_page(): # If the API key fails, redirect to the settings page: if not helper.key_test(): return redirect(BASE_PATH+url_for('settings_page')) + # General error checks. See the function for more info: + if helper.startup_checks() != "Pass": return redirect(BASE_PATH+url_for('error_page')) return render_template('overview.html', render_page = renderer.render_overview(), @@ -59,7 +61,9 @@ def overview_page(): def machines_page(): # If the API key fails, redirect to the settings page: if not helper.key_test(): return redirect(BASE_PATH+url_for('settings_page')) - + # General error checks. See the function for more info: + if helper.startup_checks() != "Pass": return redirect(BASE_PATH+url_for('error_page')) + cards = renderer.render_machines_cards() return render_template('machines.html', cards = cards, @@ -73,6 +77,8 @@ def machines_page(): def users_page(): # If the API key fails, redirect to the settings page: if not helper.key_test(): return redirect(BASE_PATH+url_for('settings_page')) + # General error checks. See the function for more info: + if helper.startup_checks() != "Pass": return redirect(BASE_PATH+url_for('error_page')) cards = renderer.render_users_cards() return render_template('users.html', @@ -85,19 +91,29 @@ def users_page(): @app.route(BASE_PATH+'/settings', methods=('GET', 'POST')) @app.route('/settings', methods=('GET', 'POST')) def settings_page(): + # General error checks. See the function for more info: + if helper.startup_checks() != "Pass": return redirect(BASE_PATH+url_for('error_page')) url = headscale.get_url() api_key = headscale.get_api_key() - return render_template('settings.html', - url = url, - COLOR_NAV = COLOR_NAV, - COLOR_BTN = COLOR_BTN, - HS_VERSION = HS_VERSION, - APP_VERSION = APP_VERSION, - GIT_COMMIT = GIT_COMMIT, - GIT_BRANCH = GIT_BRANCH, - BUILD_DATE = BUILD_DATE - ) + return render_template( + 'settings.html', + url = url, + COLOR_NAV = COLOR_NAV, + COLOR_BTN = COLOR_BTN, + HS_VERSION = HS_VERSION, + APP_VERSION = APP_VERSION, + GIT_COMMIT = GIT_COMMIT, + GIT_BRANCH = GIT_BRANCH, + BUILD_DATE = BUILD_DATE + ) + +@app.route(BASE_PATH+'/error', methods=('GET')) +@app.route('/error', methods=('GET')) +def error_page(): + return render_template('error.html', + ERROR_MESSAGE = helper.startup_checks() + ) ######################################################################################## # /api pages @@ -170,7 +186,6 @@ def save_key_page(): else: return "Key failed testing. Check your key" else: return "Key did not save properly. Check logs" - ######################################################################################## # Machine API Endpoints ######################################################################################## diff --git a/templates/error.html b/templates/error.html new file mode 100644 index 0000000..b9be543 --- /dev/null +++ b/templates/error.html @@ -0,0 +1,74 @@ + + + + ●::[●●] {% block title %} {% endblock %} + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{ ERROR_MESSAGE }} +
+ + + + + + + + \ No newline at end of file