2023-04-03 12:11:45 +00:00
|
|
|
import logging
|
|
|
|
|
import os
|
2023-02-20 17:23:05 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
import requests
|
2023-02-28 13:07:07 +09:00
|
|
|
from flask import Flask
|
2023-02-06 04:58:09 +00:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
import headscale
|
|
|
|
|
|
|
|
|
|
LOG_LEVEL = os.environ["LOG_LEVEL"].replace('"', "").upper()
|
2023-02-28 14:24:46 +09:00
|
|
|
# Initiate the Flask application and logging:
|
2023-02-27 22:21:51 +09:00
|
|
|
app = Flask(__name__, static_url_path="/static")
|
2023-02-28 14:24:46 +09:00
|
|
|
match LOG_LEVEL:
|
2023-04-03 12:11:45 +00:00
|
|
|
case "DEBUG":
|
|
|
|
|
app.logger.setLevel(logging.DEBUG)
|
|
|
|
|
case "INFO":
|
|
|
|
|
app.logger.setLevel(logging.INFO)
|
|
|
|
|
case "WARNING":
|
|
|
|
|
app.logger.setLevel(logging.WARNING)
|
|
|
|
|
case "ERROR":
|
|
|
|
|
app.logger.setLevel(logging.ERROR)
|
|
|
|
|
case "CRITICAL":
|
|
|
|
|
app.logger.setLevel(logging.CRITICAL)
|
|
|
|
|
|
2023-02-15 19:02:14 +09:00
|
|
|
|
2023-02-22 21:34:35 +09:00
|
|
|
def pretty_print_duration(duration, delta_type=""):
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Prints a duration in human-readable formats"""
|
2023-02-22 22:01:18 +09:00
|
|
|
days, seconds = duration.days, duration.seconds
|
2023-04-03 12:11:45 +00:00
|
|
|
hours = days * 24 + seconds // 3600
|
|
|
|
|
mins = (seconds % 3600) // 60
|
|
|
|
|
secs = seconds % 60
|
2023-02-22 22:20:36 +09:00
|
|
|
if delta_type == "expiry":
|
2023-04-03 12:11:45 +00:00
|
|
|
if days > 730:
|
|
|
|
|
return "in greater than two years"
|
|
|
|
|
if days > 365:
|
|
|
|
|
return "in greater than a year"
|
|
|
|
|
if days > 0:
|
|
|
|
|
return (
|
|
|
|
|
"in " + str(days) + " days" if days > 1 else "in " + str(days) + " day"
|
|
|
|
|
)
|
|
|
|
|
if hours > 0:
|
|
|
|
|
return (
|
|
|
|
|
"in " + str(hours) + " hours"
|
|
|
|
|
if hours > 1
|
|
|
|
|
else "in " + str(hours) + " hour"
|
|
|
|
|
)
|
|
|
|
|
if mins > 0:
|
|
|
|
|
return (
|
|
|
|
|
"in " + str(mins) + " minutes"
|
|
|
|
|
if mins > 1
|
|
|
|
|
else "in " + str(mins) + " minute"
|
|
|
|
|
)
|
|
|
|
|
return (
|
|
|
|
|
"in " + str(secs) + " seconds"
|
|
|
|
|
if secs >= 1 or secs == 0
|
|
|
|
|
else "in " + str(secs) + " second"
|
|
|
|
|
)
|
|
|
|
|
if days > 730:
|
|
|
|
|
return "over two years ago"
|
|
|
|
|
if days > 365:
|
|
|
|
|
return "over a year ago"
|
|
|
|
|
if days > 0:
|
|
|
|
|
return str(days) + " days ago" if days > 1 else str(days) + " day ago"
|
|
|
|
|
if hours > 0:
|
|
|
|
|
return str(hours) + " hours ago" if hours > 1 else str(hours) + " hour ago"
|
|
|
|
|
if mins > 0:
|
|
|
|
|
return str(mins) + " minutes ago" if mins > 1 else str(mins) + " minute ago"
|
|
|
|
|
return (
|
|
|
|
|
str(secs) + " seconds ago"
|
|
|
|
|
if secs >= 1 or secs == 0
|
|
|
|
|
else str(secs) + " second ago"
|
|
|
|
|
)
|
|
|
|
|
|
2023-02-27 20:15:44 +09:00
|
|
|
|
2023-02-06 04:58:09 +00:00
|
|
|
def text_color_duration(duration):
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Prints a color based on duratioin (imported as seconds)"""
|
2023-02-17 22:24:58 +09:00
|
|
|
|
2023-02-06 04:58:09 +00:00
|
|
|
days, seconds = duration.days, duration.seconds
|
2023-04-03 12:11:45 +00:00
|
|
|
hours = days * 24 + seconds // 3600
|
|
|
|
|
mins = (seconds % 3600) // 60
|
|
|
|
|
secs = seconds % 60
|
|
|
|
|
if days > 30:
|
|
|
|
|
return "grey-text "
|
|
|
|
|
if days > 14:
|
|
|
|
|
return "red-text text-darken-2 "
|
|
|
|
|
if days > 5:
|
|
|
|
|
return "deep-orange-text text-lighten-1"
|
|
|
|
|
if days > 1:
|
|
|
|
|
return "deep-orange-text text-lighten-1"
|
|
|
|
|
if hours > 12:
|
|
|
|
|
return "orange-text "
|
|
|
|
|
if hours > 1:
|
|
|
|
|
return "orange-text text-lighten-2"
|
|
|
|
|
if hours == 1:
|
|
|
|
|
return "yellow-text "
|
|
|
|
|
if mins > 15:
|
|
|
|
|
return "yellow-text text-lighten-2"
|
|
|
|
|
if mins > 5:
|
|
|
|
|
return "green-text text-lighten-3"
|
|
|
|
|
if secs > 30:
|
|
|
|
|
return "green-text text-lighten-2"
|
2023-02-17 22:24:58 +09:00
|
|
|
return "green-text "
|
2023-02-06 04:58:09 +00:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
|
2023-02-16 20:17:36 +09:00
|
|
|
def key_check():
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Checks the validity of a Headsclae API key and renews it if it's nearing expiration"""
|
|
|
|
|
api_key = headscale.get_api_key()
|
|
|
|
|
url = headscale.get_url()
|
2023-02-06 04:58:09 +00:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
# Test the API key. If the test fails, return a failure.
|
2023-02-06 04:58:09 +00:00
|
|
|
# AKA, if headscale returns Unauthorized, fail:
|
2023-02-27 22:45:12 +09:00
|
|
|
app.logger.info("Testing API key validity.")
|
2023-02-06 04:58:09 +00:00
|
|
|
status = headscale.test_api_key(url, api_key)
|
2023-04-03 12:11:45 +00:00
|
|
|
if status != 200:
|
|
|
|
|
app.logger.info(
|
|
|
|
|
"Got a non-200 response from Headscale. Test failed (Response: %i)",
|
|
|
|
|
status,
|
|
|
|
|
)
|
2023-02-27 20:15:44 +09:00
|
|
|
return False
|
2023-02-06 04:58:09 +00:00
|
|
|
else:
|
2023-02-27 22:45:12 +09:00
|
|
|
app.logger.info("Key check passed.")
|
2023-02-06 04:58:09 +00:00
|
|
|
# Check if the key needs to be renewed
|
2023-02-17 22:24:58 +09:00
|
|
|
headscale.renew_api_key(url, api_key)
|
2023-02-06 04:58:09 +00:00
|
|
|
return True
|
|
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
|
|
|
|
|
def get_color(import_id, item_type=""):
|
|
|
|
|
"""Sets colors for users/namespaces"""
|
2023-02-06 04:58:09 +00:00
|
|
|
# Define the colors... Seems like a good number to start with
|
2023-03-22 20:35:11 +09:00
|
|
|
if item_type == "failover":
|
|
|
|
|
colors = [
|
|
|
|
|
"teal lighten-1",
|
|
|
|
|
"blue lighten-1",
|
|
|
|
|
"blue-grey lighten-1",
|
|
|
|
|
"indigo lighten-2",
|
|
|
|
|
"brown lighten-1",
|
|
|
|
|
"grey lighten-1",
|
|
|
|
|
"indigo lighten-2",
|
|
|
|
|
"deep-orange lighten-1",
|
|
|
|
|
"yellow lighten-2",
|
|
|
|
|
"purple lighten-2",
|
|
|
|
|
]
|
|
|
|
|
index = import_id % len(colors)
|
|
|
|
|
return colors[index]
|
2023-02-17 22:24:58 +09:00
|
|
|
if item_type == "text":
|
2023-02-06 04:58:09 +00:00
|
|
|
colors = [
|
|
|
|
|
"red-text text-lighten-1",
|
|
|
|
|
"teal-text text-lighten-1",
|
|
|
|
|
"blue-text text-lighten-1",
|
|
|
|
|
"blue-grey-text text-lighten-1",
|
|
|
|
|
"indigo-text text-lighten-2",
|
|
|
|
|
"green-text text-lighten-1",
|
|
|
|
|
"deep-orange-text text-lighten-1",
|
|
|
|
|
"yellow-text text-lighten-2",
|
|
|
|
|
"purple-text text-lighten-2",
|
|
|
|
|
"indigo-text text-lighten-2",
|
|
|
|
|
"brown-text text-lighten-1",
|
|
|
|
|
"grey-text text-lighten-1",
|
|
|
|
|
]
|
2023-02-17 22:24:58 +09:00
|
|
|
index = import_id % len(colors)
|
2023-02-06 04:58:09 +00:00
|
|
|
return colors[index]
|
2023-02-17 22:24:58 +09:00
|
|
|
colors = [
|
|
|
|
|
"red lighten-1",
|
|
|
|
|
"teal lighten-1",
|
|
|
|
|
"blue lighten-1",
|
|
|
|
|
"blue-grey lighten-1",
|
|
|
|
|
"indigo lighten-2",
|
|
|
|
|
"green lighten-1",
|
|
|
|
|
"deep-orange lighten-1",
|
|
|
|
|
"yellow lighten-2",
|
|
|
|
|
"purple lighten-2",
|
|
|
|
|
"indigo lighten-2",
|
|
|
|
|
"brown lighten-1",
|
|
|
|
|
"grey lighten-1",
|
|
|
|
|
]
|
|
|
|
|
index = import_id % len(colors)
|
|
|
|
|
return colors[index]
|
|
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
|
2023-02-20 17:23:05 +09:00
|
|
|
def format_message(error_type, title, message):
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Defines a generic 'collection' as error/warning/info messages"""
|
2023-02-15 12:31:22 +09:00
|
|
|
content = """
|
|
|
|
|
<ul class="collection">
|
|
|
|
|
<li class="collection-item avatar">
|
|
|
|
|
"""
|
2023-04-03 12:11:45 +00:00
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
match error_type.lower():
|
2023-02-15 12:31:22 +09:00
|
|
|
case "warning":
|
2023-04-03 12:11:45 +00:00
|
|
|
icon = """<i class="material-icons circle yellow">priority_high</i>"""
|
|
|
|
|
title = """<span class="title">Warning - """ + title + """</span>"""
|
2023-02-15 12:31:22 +09:00
|
|
|
case "success":
|
2023-04-03 12:11:45 +00:00
|
|
|
icon = """<i class="material-icons circle green">check</i>"""
|
|
|
|
|
title = """<span class="title">Success - """ + title + """</span>"""
|
2023-02-15 12:31:22 +09:00
|
|
|
case "error":
|
2023-04-03 12:11:45 +00:00
|
|
|
icon = """<i class="material-icons circle red">warning</i>"""
|
|
|
|
|
title = """<span class="title">Error - """ + title + """</span>"""
|
2023-02-15 12:31:22 +09:00
|
|
|
case "information":
|
2023-04-03 12:11:45 +00:00
|
|
|
icon = """<i class="material-icons circle grey">help</i>"""
|
|
|
|
|
title = """<span class="title">Information - """ + title + """</span>"""
|
2023-02-15 12:31:22 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
content = content + icon + title + message
|
|
|
|
|
content = (
|
|
|
|
|
content
|
|
|
|
|
+ """
|
2023-02-15 12:31:22 +09:00
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
"""
|
2023-04-03 12:11:45 +00:00
|
|
|
)
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-02-15 12:31:22 +09:00
|
|
|
return content
|
|
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
|
2023-02-16 21:48:05 +09:00
|
|
|
def access_checks():
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Checks various items before each page load to ensure permissions are correct"""
|
2023-02-15 12:31:22 +09:00
|
|
|
url = headscale.get_url()
|
|
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
# Return an error message if things fail.
|
2023-02-15 12:31:22 +09:00
|
|
|
# Return a formatted error message for EACH fail.
|
2023-04-03 12:11:45 +00:00
|
|
|
checks_passed = True # Default to true. Set to false when any checks fail.
|
|
|
|
|
data_readable = False # Checks R permissions of /data
|
|
|
|
|
data_writable = False # Checks W permissions of /data
|
|
|
|
|
data_executable = False # Execute on directories allows file access
|
|
|
|
|
file_readable = False # Checks R permissions of /data/key.txt
|
|
|
|
|
file_writable = False # Checks W permissions of /data/key.txt
|
|
|
|
|
file_exists = False # Checks if /data/key.txt exists
|
|
|
|
|
config_readable = False # Checks if the headscale configuration file is readable
|
2023-02-15 12:31:22 +09:00
|
|
|
|
2023-02-15 20:58:27 +09:00
|
|
|
# Check 1: Check: the Headscale server is reachable:
|
2023-02-15 15:50:15 +09:00
|
|
|
server_reachable = False
|
2023-04-03 12:11:45 +00:00
|
|
|
response = requests.get(str(url) + "/health")
|
2023-02-15 20:13:27 +09:00
|
|
|
if response.status_code == 200:
|
|
|
|
|
server_reachable = True
|
2023-02-17 22:24:58 +09:00
|
|
|
else:
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("Headscale URL: Response 200: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
|
2023-02-15 20:58:27 +09:00
|
|
|
# Check: /data is rwx for 1000:1000:
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/", os.R_OK):
|
|
|
|
|
data_readable = True
|
2023-02-15 20:27:30 +09:00
|
|
|
else:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data READ: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/", os.W_OK):
|
|
|
|
|
data_writable = True
|
2023-02-15 20:27:30 +09:00
|
|
|
else:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data WRITE: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/", os.X_OK):
|
|
|
|
|
data_executable = True
|
2023-02-15 20:45:51 +09:00
|
|
|
else:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data EXEC: FAILED")
|
2023-02-15 20:45:51 +09:00
|
|
|
checks_passed = False
|
2023-02-15 14:43:38 +09:00
|
|
|
|
2023-02-15 20:58:27 +09:00
|
|
|
# Check: /data/key.txt exists and is rw:
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/key.txt", os.F_OK):
|
2023-02-15 20:33:47 +09:00
|
|
|
file_exists = True
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/key.txt", os.R_OK):
|
|
|
|
|
file_readable = True
|
2023-02-15 20:27:30 +09:00
|
|
|
else:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data/key.txt READ: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/data/key.txt", os.W_OK):
|
|
|
|
|
file_writable = True
|
2023-02-15 20:27:30 +09:00
|
|
|
else:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data/key.txt WRITE: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-04-03 12:11:45 +00:00
|
|
|
else:
|
|
|
|
|
app.logger.error("/data/key.txt EXIST: FAILED - NO ERROR")
|
2023-02-15 20:58:27 +09:00
|
|
|
|
|
|
|
|
# Check: /etc/headscale/config.yaml is readable:
|
2023-04-03 12:11:45 +00:00
|
|
|
if os.access("/etc/headscale/config.yaml", os.R_OK):
|
|
|
|
|
config_readable = True
|
|
|
|
|
elif os.access("/etc/headscale/config.yml", os.R_OK):
|
|
|
|
|
config_readable = True
|
2023-02-17 22:24:58 +09:00
|
|
|
else:
|
2023-02-27 22:45:12 +09:00
|
|
|
app.logger.error("/etc/headscale/config.y(a)ml: READ: FAILED")
|
2023-02-15 20:27:30 +09:00
|
|
|
checks_passed = False
|
2023-02-15 19:53:46 +09:00
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
if checks_passed:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.info("All startup checks passed.")
|
2023-02-16 21:39:54 +09:00
|
|
|
return "Pass"
|
2023-02-15 12:31:22 +09:00
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
message_html = ""
|
2023-02-15 12:31:22 +09:00
|
|
|
# Generate the message:
|
2023-02-15 14:43:38 +09:00
|
|
|
if not server_reachable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("Server is unreachable")
|
2023-04-03 12:11:45 +00:00
|
|
|
message = (
|
|
|
|
|
"""
|
|
|
|
|
<p>Your headscale server is either unreachable or not properly configured.
|
2023-02-17 22:24:58 +09:00
|
|
|
Please ensure your configuration is correct (Check for 200 status on
|
2023-02-15 12:31:22 +09:00
|
|
|
"""
|
2023-04-03 12:11:45 +00:00
|
|
|
+ url
|
|
|
|
|
+ """/api/v1 failed. Response: """
|
|
|
|
|
+ str(response.status_code)
|
|
|
|
|
+ """.)</p>
|
|
|
|
|
"""
|
|
|
|
|
)
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-02-20 17:23:05 +09:00
|
|
|
message_html += format_message("Error", "Headscale unreachable", message)
|
2023-02-15 19:53:46 +09:00
|
|
|
|
|
|
|
|
if not config_readable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("Headscale configuration is not readable")
|
2023-02-15 19:53:46 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/etc/headscale/config.yaml not readable. Please ensure your
|
|
|
|
|
headscale configuration file resides in /etc/headscale and
|
2023-02-15 19:53:46 +09:00
|
|
|
is named "config.yaml" or "config.yml"</p>
|
|
|
|
|
"""
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
message_html += format_message(
|
|
|
|
|
"Error", "/etc/headscale/config.yaml not readable", message
|
|
|
|
|
)
|
2023-02-15 19:53:46 +09:00
|
|
|
|
2023-02-15 14:43:38 +09:00
|
|
|
if not data_writable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data folder is not writable")
|
2023-02-15 12:31:22 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/data is not writable. Please ensure your
|
|
|
|
|
permissions are correct. /data mount should be writable
|
2023-02-15 14:43:38 +09:00
|
|
|
by UID/GID 1000:1000.</p>
|
2023-02-15 12:31:22 +09:00
|
|
|
"""
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-02-20 17:23:05 +09:00
|
|
|
message_html += format_message("Error", "/data not writable", message)
|
2023-02-15 20:14:42 +09:00
|
|
|
|
2023-02-15 14:43:38 +09:00
|
|
|
if not data_readable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data folder is not readable")
|
2023-02-15 14:43:38 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/data is not readable. Please ensure your
|
|
|
|
|
permissions are correct. /data mount should be readable
|
2023-02-15 14:43:38 +09:00
|
|
|
by UID/GID 1000:1000.</p>
|
|
|
|
|
"""
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-02-20 17:23:05 +09:00
|
|
|
message_html += format_message("Error", "/data not readable", message)
|
2023-02-15 14:43:38 +09:00
|
|
|
|
2023-02-15 20:45:51 +09:00
|
|
|
if not data_executable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data folder is not readable")
|
2023-02-15 20:45:51 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/data is not executable. Please ensure your
|
|
|
|
|
permissions are correct. /data mount should be readable
|
2023-02-15 20:45:51 +09:00
|
|
|
by UID/GID 1000:1000. (chown 1000:1000 /path/to/data && chmod -R 755 /path/to/data)</p>
|
|
|
|
|
"""
|
|
|
|
|
|
2023-02-20 17:23:05 +09:00
|
|
|
message_html += format_message("Error", "/data not executable", message)
|
2023-02-15 20:45:51 +09:00
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
if file_exists:
|
|
|
|
|
# If it doesn't exist, we assume the user hasn't created it yet.
|
|
|
|
|
# Just redirect to the settings page to enter an API Key
|
2023-02-15 16:16:02 +09:00
|
|
|
if not file_writable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data/key.txt is not writable")
|
2023-02-15 16:16:02 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/data/key.txt is not writable. Please ensure your
|
|
|
|
|
permissions are correct. /data mount should be writable
|
2023-02-15 16:16:02 +09:00
|
|
|
by UID/GID 1000:1000.</p>
|
|
|
|
|
"""
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
message_html += format_message(
|
|
|
|
|
"Error", "/data/key.txt not writable", message
|
|
|
|
|
)
|
2023-02-15 20:14:42 +09:00
|
|
|
|
2023-02-15 16:16:02 +09:00
|
|
|
if not file_readable:
|
2023-02-28 13:29:31 +09:00
|
|
|
app.logger.critical("/data/key.txt is not readable")
|
2023-02-15 16:16:02 +09:00
|
|
|
message = """
|
2023-02-17 22:24:58 +09:00
|
|
|
<p>/data/key.txt is not readable. Please ensure your
|
|
|
|
|
permissions are correct. /data mount should be readable
|
2023-02-15 16:16:02 +09:00
|
|
|
by UID/GID 1000:1000.</p>
|
|
|
|
|
"""
|
2023-02-15 20:33:25 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
message_html += format_message(
|
|
|
|
|
"Error", "/data/key.txt not readable", message
|
|
|
|
|
)
|
2023-02-15 20:14:42 +09:00
|
|
|
|
2023-02-17 22:24:58 +09:00
|
|
|
return message_html
|
2023-02-16 20:17:36 +09:00
|
|
|
|
2023-04-03 12:11:45 +00:00
|
|
|
|
2023-02-16 21:30:49 +09:00
|
|
|
def load_checks():
|
2023-04-03 12:11:45 +00:00
|
|
|
"""Bundles all the checks into a single function to call easier"""
|
2023-02-16 20:17:36 +09:00
|
|
|
# General error checks. See the function for more info:
|
2023-04-03 12:11:45 +00:00
|
|
|
if access_checks() != "Pass":
|
|
|
|
|
return "error_page"
|
2023-02-16 20:17:36 +09:00
|
|
|
# If the API key fails, redirect to the settings page:
|
2023-04-03 12:11:45 +00:00
|
|
|
if not key_check():
|
|
|
|
|
return "settings_page"
|
2023-02-17 22:24:58 +09:00
|
|
|
return "Pass"
|