diff --git a/src/judas_server/web/__init__.py b/src/judas_server/web/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/judas_server/web/routes/__init__.py b/src/judas_server/web/routes/__init__.py deleted file mode 100644 index 2ac5931..0000000 --- a/src/judas_server/web/routes/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .auth import auth_bp -from .index import index_bp -from .panel import panel_bp - -__all__ = ["auth_bp", "index_bp", "panel_bp"] diff --git a/src/judas_server/web/routes/api.py b/src/judas_server/web/routes/api.py deleted file mode 100644 index 7d8ef3b..0000000 --- a/src/judas_server/web/routes/api.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import annotations - -import threading -from typing import TYPE_CHECKING - -import flask -import flask_login - -if TYPE_CHECKING: - from werkzeug.wrappers import Response - -bp: flask.Blueprint = flask.Blueprint("api", __name__, url_prefix="/api") - - -@bp.route("/client/", methods=["GET"]) -@flask_login.login_required -def get_client_data(client_id: str) -> tuple[Response, int]: - """API endpoint to get client data by ID. - - Args: - client_id (str): The ID of the client. - - Returns: - Response: JSON response with client data or error message. - """ - backend = flask.current_app.config["BACKEND"] - data = backend.get_client_data(client_id) - if data is None: - return flask.jsonify({"error": "Client not found"}), 404 - return flask.jsonify(data), 200 - - -@bp.route("/clients", methods=["GET"]) -@flask_login.login_required -def list_clients() -> tuple[Response, int]: - """API endpoint to list all clients. - - Returns: - Response: JSON response with list of client IDs. - """ - backend = flask.current_app.config["BACKEND"] - client_ids = list(backend.clients.keys()) - return flask.jsonify({"clients": client_ids}), 200 - - -def emit_polled_data(app, socketio): - backend = app.config["BACKEND"] - - def poll_loop(): - import time - - while True: - data = {} - for client_id in backend.clients.keys(): - data[client_id] = backend.get_client_data(client_id) - socketio.emit("update_data", data) - - time.sleep(1) - - threading.Thread(name="Socketio", target=poll_loop, daemon=True).start() diff --git a/src/judas_server/web/routes/auth.py b/src/judas_server/web/routes/auth.py deleted file mode 100644 index d78594d..0000000 --- a/src/judas_server/web/routes/auth.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import annotations - -from typing import TYPE_CHECKING - -import flask -import flask_login - -from judas_server.web.user import User - -if TYPE_CHECKING: - from werkzeug.wrappers import Response - -auth_bp: flask.Blueprint = flask.Blueprint( - "auth", __name__, url_prefix="/auth" -) - - -@auth_bp.route("/login", methods=["GET", "POST"]) -def login() -> Response | str: - """Handles user login via password form.""" - if flask.request.method == "POST": - password = flask.request.form.get("password", "") - if password == flask.current_app.config["PASSWORD"]: - user = User("admin") - flask_login.login_user(user) - next_page = flask.request.args.get("next") - return flask.redirect(next_page or flask.url_for("index.index")) - # return flask.redirect(flask.url_for("panel.panel")) - else: - return flask.render_template( - "login.html", - error="Invalid credentials.", - ) - return flask.render_template("login.html") - - -@auth_bp.route("/logout") -@flask_login.login_required -def logout() -> Response: - """Logs out the current user.""" - flask_login.logout_user() - return flask.redirect(flask.url_for("index.index")) diff --git a/src/judas_server/web/routes/client_details.py b/src/judas_server/web/routes/client_details.py deleted file mode 100644 index c9e1d6e..0000000 --- a/src/judas_server/web/routes/client_details.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import annotations - -from typing import TYPE_CHECKING -import flask -import flask_login - -if TYPE_CHECKING: - from judas_server.backend import BackendServer - from judas_server.backend.client import Client - -bp: flask.Blueprint = flask.Blueprint( - "client_details", __name__, url_prefix="/client" -) - - -@bp.route("/") -@flask_login.login_required -def client_details(client_id: str) -> str: - """Renders the client details page for a specific client. - - Args: - client_id: The ID of the client to display details for. - """ - backend: BackendServer = flask.current_app.config["BACKEND"] - client: Client | None = backend.clients.get(client_id) - - if not client: - flask.abort(404, description="Client not found") - - return flask.render_template("client_details.html", client=client) diff --git a/src/judas_server/web/routes/index.py b/src/judas_server/web/routes/index.py deleted file mode 100644 index 6940868..0000000 --- a/src/judas_server/web/routes/index.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import annotations - -from typing import TYPE_CHECKING - -import flask -import flask_login - -if TYPE_CHECKING: - from werkzeug.wrappers import Response - -index_bp: flask.Blueprint = flask.Blueprint("index", __name__) - - -@index_bp.route("/") -def index() -> Response | str: - """Renders the index page.""" - return flask.render_template( - "index.html", logged=flask_login.current_user.is_authenticated - ) diff --git a/src/judas_server/web/routes/panel.py b/src/judas_server/web/routes/panel.py deleted file mode 100644 index a3cbe1d..0000000 --- a/src/judas_server/web/routes/panel.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import annotations - -import flask -import flask_login - -panel_bp: flask.Blueprint = flask.Blueprint( - "panel", __name__, url_prefix="/panel" -) - - -@panel_bp.route("") -@flask_login.login_required -def panel() -> str: - """Renders the main panel page with PC details. - - Returns: - Rendered HTML template with PC details. - """ - return flask.render_template("panel.html") diff --git a/src/judas_server/web/static/css/palette.css b/src/judas_server/web/static/css/palette.css deleted file mode 100644 index db0a307..0000000 --- a/src/judas_server/web/static/css/palette.css +++ /dev/null @@ -1,80 +0,0 @@ -:root { - --ctp-rosewater: #f5e0dc; - --ctp-rosewater-rgb: 245 224 220; - --ctp-rosewater-hsl: 9.600 55.556% 91.176%; - --ctp-flamingo: #f2cdcd; - --ctp-flamingo-rgb: 242 205 205; - --ctp-flamingo-hsl: 0.000 58.730% 87.647%; - --ctp-pink: #f5c2e7; - --ctp-pink-rgb: 245 194 231; - --ctp-pink-hsl: 316.471 71.831% 86.078%; - --ctp-mauve: #cba6f7; - --ctp-mauve-rgb: 203 166 247; - --ctp-mauve-hsl: 267.407 83.505% 80.980%; - --ctp-red: #f38ba8; - --ctp-red-rgb: 243 139 168; - --ctp-red-hsl: 343.269 81.250% 74.902%; - --ctp-maroon: #eba0ac; - --ctp-maroon-rgb: 235 160 172; - --ctp-maroon-hsl: 350.400 65.217% 77.451%; - --ctp-peach: #fab387; - --ctp-peach-rgb: 250 179 135; - --ctp-peach-hsl: 22.957 92.000% 75.490%; - --ctp-yellow: #f9e2af; - --ctp-yellow-rgb: 249 226 175; - --ctp-yellow-hsl: 41.351 86.047% 83.137%; - --ctp-green: #a6e3a1; - --ctp-green-rgb: 166 227 161; - --ctp-green-hsl: 115.455 54.098% 76.078%; - --ctp-teal: #94e2d5; - --ctp-teal-rgb: 148 226 213; - --ctp-teal-hsl: 170.000 57.353% 73.333%; - --ctp-sky: #89dceb; - --ctp-sky-rgb: 137 220 235; - --ctp-sky-hsl: 189.184 71.014% 72.941%; - --ctp-sapphire: #74c7ec; - --ctp-sapphire-rgb: 116 199 236; - --ctp-sapphire-hsl: 198.500 75.949% 69.020%; - --ctp-blue: #89b4fa; - --ctp-blue-rgb: 137 180 250; - --ctp-blue-hsl: 217.168 91.870% 75.882%; - --ctp-lavender: #b4befe; - --ctp-lavender-rgb: 180 190 254; - --ctp-lavender-hsl: 231.892 97.368% 85.098%; - --ctp-text: #cdd6f4; - --ctp-text-rgb: 205 214 244; - --ctp-text-hsl: 226.154 63.934% 88.039%; - --ctp-subtext1: #bac2de; - --ctp-subtext1-rgb: 186 194 222; - --ctp-subtext1-hsl: 226.667 35.294% 80.000%; - --ctp-subtext0: #a6adc8; - --ctp-subtext0-rgb: 166 173 200; - --ctp-subtext0-hsl: 227.647 23.611% 71.765%; - --ctp-overlay2: #9399b2; - --ctp-overlay2-rgb: 147 153 178; - --ctp-overlay2-hsl: 228.387 16.757% 63.725%; - --ctp-overlay1: #7f849c; - --ctp-overlay1-rgb: 127 132 156; - --ctp-overlay1-hsl: 229.655 12.775% 55.490%; - --ctp-overlay0: #6c7086; - --ctp-overlay0-rgb: 108 112 134; - --ctp-overlay0-hsl: 230.769 10.744% 47.451%; - --ctp-surface2: #585b70; - --ctp-surface2-rgb: 88 91 112; - --ctp-surface2-hsl: 232.500 12.000% 39.216%; - --ctp-surface1: #45475a; - --ctp-surface1-rgb: 69 71 90; - --ctp-surface1-hsl: 234.286 13.208% 31.176%; - --ctp-surface0: #313244; - --ctp-surface0-rgb: 49 50 68; - --ctp-surface0-hsl: 236.842 16.239% 22.941%; - --ctp-base: #1e1e2e; - --ctp-base-rgb: 30 30 46; - --ctp-base-hsl: 240.000 21.053% 14.902%; - --ctp-mantle: #181825; - --ctp-mantle-rgb: 24 24 37; - --ctp-mantle-hsl: 240.000 21.311% 11.961%; - --ctp-crust: #11111b; - --ctp-crust-rgb: 17 17 27; - --ctp-crust-hsl: 240.000 22.727% 8.627%; -} diff --git a/src/judas_server/web/static/css/style.css b/src/judas_server/web/static/css/style.css deleted file mode 100644 index 202b855..0000000 --- a/src/judas_server/web/static/css/style.css +++ /dev/null @@ -1,262 +0,0 @@ -@import url("https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-rounded/css/uicons-regular-rounded.css"); -@import url("https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-straight/css/uicons-regular-straight.css"); -@import url("https://cdn-uicons.flaticon.com/2.6.0/uicons-solid-rounded/css/uicons-solid-rounded.css"); -@import url("https://cdn-uicons.flaticon.com/2.6.0/uicons-solid-straight/css/uicons-solid-straight.css"); -@import url("https://cdn-uicons.flaticon.com/2.6.0/uicons-bold-rounded/css/uicons-bold-rounded.css"); - -@import "palette.css"; - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - background-color: var(--ctp-base); - font-family: sans-serif; - color: var(--ctp-text); - min-height: 100vh; -} - -.fi { - vertical-align: middle; -} - -input { - font-family: inherit; - color: #eceff4; - background-color: var(--ctp-crust); - border: none; - border-radius: 0.25rem; - padding: 0.25rem; -} - -a { - color: var(--ctp-blue); - text-decoration: none; -} - -#wrapper { - display: flex; - flex-direction: column; - min-height: 100vh; -} - -header { - display: flex; - justify-content: space-between; - align-items: center; - background-color: var(--ctp-mantle); - padding: 0.5rem 1rem; -} - -header h2 { - font-family: monospace, sans-serif; -} - -main { - display: flex; - flex-grow: 1; -} - -aside { - width: 20rem; - background-color: var(--ctp-base); - border-right: 4px solid var(--ctp-mantle); -} - -#content { - display: flex; - flex-direction: column; - flex-grow: 1; -} - -header a { - text-decoration: none; - /* color: var(--nord-fg0); */ -} - -.button { - display: inline-block; - padding: 0.25rem 0.5rem; - background-color: var(--ctp-lavender); - color: var(--ctp-base); - border: none; - border-radius: 0.25rem; - text-decoration: none; -} - -.button:hover { - background-color: var(--ctp-mauve); - cursor: pointer; -} - -.button:active { - background-color: var(--ctp-sapphire); -} - -.center { - text-align: center; -} - -.error-container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - margin: 1rem; - padding: 1rem; - background-color: var(--ctp-surface0); - color: var(--ctp-red); - border: 6px solid var(--ctp-red); - border-radius: 24px; -} - -.center-table { - margin: 0 auto; - width: 100%; -} - -.select-table { - border-collapse: collapse; - border: 2px solid var(--ctp-surface0); -} - -.select-table thead { - position: sticky; - top: -1px; - z-index: 2; -} - -.select-table th, -.select-table td { - padding: 0.5rem; - text-align: center; - border: 1px solid var(--ctp-surface0); - border-collapse: collapse; -} - -.select-table th { - background-color: var(--ctp-surface1); - color: var(--nord-fg0); -} - -.select-table a { - display: block; - text-decoration: none; - transition: 0.1s ease-in-out; -} - -.select-table tr { - transition: 0.1s ease-in-out; -} - -.select-table tr:hover { - background-color: var(--ctp-surface0); -} - -.select-table tr:hover a { - color: var(--ctp-base); -} - -.red-bg { - background-color: var(--ctp-red); -} - -.yellow-bg { - background-color: var(--ctp-yellow); -} - -.green-bg { - background-color: var(--ctp-green); -} - -.button-container { - display: flex; - justify-content: space-between; - align-items: center; - gap: 1rem; -} - -.link { - transition: 0.3s ease-in-out; -} - -.link:hover { - color: var(--ctp-blue); -} - -.details-table tr td:first-child { - font-weight: 900; - background-color: var(--ctp-surface0); - white-space: nowrap; - width: 1%; -} - -.details-table { - border-collapse: collapse; - border: 2px solid var(--ctp-surface1); -} - -.details-table th, -.details-table td { - padding: 0.5rem; - text-align: left; - border: 1px solid var(--ctp-text); - border-collapse: collapse; -} - -#notify { - display: none; - position: fixed; - top: 3rem; - right: 50%; - transform: translateX(50%); - background-color: var(--ctp-surface1); - padding: 1rem 2rem; - border: 4px solid var(--ctp-text); - border-radius: 1rem; - opacity: 0.8; -} - -#no-connection-message { - color: var(--ctp-red); -} - -#no-connection-message i { - padding-right: 0.5rem; - font-size: 1.5rem; - vertical-align: middle; - color: var(--ctp-red); -} - -ul#client-list { - list-style: none; - display: flex; - flex-direction: column; -} - -ul#client-list li { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0 0.5rem; - cursor: default; -} - -ul#client-list li:hover { - background-color: var(--ctp-surface0); -} - -ul#client-list li i { - line-height: 0; -} - -ul#client-list li a { - display: block; - width: 100%; - color: var(--ctp-text); - text-decoration: none; - cursor: default; -} diff --git a/src/judas_server/web/static/js/panel.js b/src/judas_server/web/static/js/panel.js deleted file mode 100644 index 4e11461..0000000 --- a/src/judas_server/web/static/js/panel.js +++ /dev/null @@ -1,163 +0,0 @@ -$(document).ready(function () { - const socket = io(); - - const showNotify = (message) => { - $("#notify").stop().fadeIn(); - $("#notify").text(message); - setTimeout(() => { - $("#notify").fadeOut(); - }, 3000); - }; - - const loadClientDetails = (clientId) => { - fetch(`/client/${clientId}`) - .then((response) => response.text()) - .then((html) => { - $("#content").html(html); - }) - .catch((error) => { - console.error("Error fetching client details:", error); - }); - }; - - // load client_details for the client specified in the URL - const urlParams = new URLSearchParams(window.location.search); - const clientId = urlParams.get("client"); - if (clientId) { - loadClientDetails(clientId); - $(`#client-list a[href="?client=${clientId}"]`).addClass("active"); - } - - $("#notify").hide(); - - socket.on("connect", () => { - console.log("Connected to server"); - $("#no-connection-message").hide(); - showNotify("Connected to server"); - }); - - socket.on("disconnect", () => { - console.log("Disconnected from server"); - $("#no-connection-message").show(); - showNotify("Disconnected from server"); - }); - - socket.on("update_data", (data) => { - const clientList = $("#client-list"); - const existingItems = {}; - - // Index current
  • by clientId - clientList.children("li").each(function () { - const a = $(this).find("a"); - if (a.length) { - const clientId = a.attr("href").substring(1); - existingItems[clientId] = $(this); - } - }); - - // Track which clientIds are still present - const seen = new Set(); - - Object.entries(data).forEach(([clientId, client]) => { - seen.add(clientId); - - // Build icon - const iconElement = document.createElement("i"); - switch (client.status) { - case "online": - iconElement.className = "fi fi-sr-play text-ctp-green"; - break; - case "offline": - iconElement.className = "fi fi-sr-stop text-ctp-red"; - break; - case "pending": - iconElement.className = "fi fi-sr-pending text-ctp-yellow"; - break; - case "stale": - iconElement.className = "fi fi-sr-skull text-ctp-text"; - break; - default: - iconElement.className = "fi fi-rr-question text-ctp-gray"; - } - - // Time since last seen - const lastSeen = new Date(client.last_seen * 1000); - const now = new Date(); - const timeSinceLastSeen = Math.floor((now - lastSeen) / 1000); - const days = Math.floor(timeSinceLastSeen / 86400); - const hours = Math.floor((timeSinceLastSeen % 86400) / 3600); - const minutes = Math.floor((timeSinceLastSeen % 3600) / 60); - const seconds = timeSinceLastSeen % 60; - let timeSinceLastSeenText = ""; - if (days > 0) timeSinceLastSeenText += `${days}d `; - if (hours > 0) timeSinceLastSeenText += `${hours}h `; - if (minutes > 0) timeSinceLastSeenText += `${minutes}m `; - if (seconds > 0) timeSinceLastSeenText += `${seconds}s`; - - timeSinceLastSeenText = timeSinceLastSeenText.trim() || "0s"; - - let statusText = `${client.id} (${timeSinceLastSeenText})`; - - // check if
  • exists - if (existingItems[clientId]) { - // update if needed - const li = existingItems[clientId]; - const a = li.find("a"); - if (a.text() !== statusText) { - a.text(statusText); - } - - li.attr( - "title", - `Status: ${client.status}\nLast Seen: ${lastSeen.toISOString()}`, - ); - - // update icon - const icon = li.find("i")[0]; - if (icon) { - icon.className = iconElement.className; - } - } else { - // add new
  • - const li = $("
  • "); - li.append(iconElement); - const a = $("") - .text(statusText) - .attr("href", `?client=${clientId}`); - - li.attr( - "title", - `Status: ${client.status}\nLast Seen: ${lastSeen.toISOString()}`, - ); - - li.append(a); - clientList.append(li); - } - }); - - // Remove
  • for clients no longer present - Object.keys(existingItems).forEach((clientId) => { - if (!seen.has(clientId)) { - existingItems[clientId].remove(); - } - }); - - // Re-bind click handlers - $("#client-list li > a") - .off("click") - .on("click", function (e) { - let clientId = $(this).attr("href").substring(1); - // this is client=clientId - - clientId = clientId.replace("client=", ""); - - loadClientDetails(clientId); - $("#client-list a").removeClass("bg-ctp-surface0"); - $(this).addClass("bg-ctp-surface0"); - e.preventDefault(); - - let newUrl = `${window.location.pathname}?client=${clientId}`; - window.history.pushState({ path: newUrl }, "", newUrl); - }); - }); -}); diff --git a/src/judas_server/web/templates/base/base.html b/src/judas_server/web/templates/base/base.html deleted file mode 100644 index 27c5dfb..0000000 --- a/src/judas_server/web/templates/base/base.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - {% block title %}{% endblock %} – judas - - - - - - - - - - - - - {% include "base/header.html" %} - - {% block content %}{% endblock %} - - {% block scripts %}{% endblock %} - - diff --git a/src/judas_server/web/templates/base/header.html b/src/judas_server/web/templates/base/header.html deleted file mode 100644 index faabfaf..0000000 --- a/src/judas_server/web/templates/base/header.html +++ /dev/null @@ -1,13 +0,0 @@ -
    -

    judas

    -

    - - No connection to server -

    - - {% if current_user.is_authenticated %} - Logout - {% else %} - Login - {% endif %} -
    diff --git a/src/judas_server/web/templates/client_details.html b/src/judas_server/web/templates/client_details.html deleted file mode 100644 index 9f3fd6c..0000000 --- a/src/judas_server/web/templates/client_details.html +++ /dev/null @@ -1,46 +0,0 @@ -
    -

    Machine {{ client.id }}

    -
    -
    -
    - -
    -
    -

    Details for client {{ client.id }}

    - -

    - Last Seen: - {{ client.last_seen }} -

    -
    -
    - - diff --git a/src/judas_server/web/templates/index.html b/src/judas_server/web/templates/index.html deleted file mode 100644 index 7c93963..0000000 --- a/src/judas_server/web/templates/index.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends "base/base.html" %} - -{% block title %}home{% endblock %} - -{% block content %} -
    -
    -

    Welcome to

    -

    judas

    -

    a remote PC fleet management system

    -
    -

    Notice: Please use this system responsibly and in accordance with all applicable laws and organizational policies.

    - {% if logged %} -

    Go to panel

    - {% else %} -

    Please log in to manage your remote PCs.

    - {% endif %} -
    -{% endblock %} - -{% block scripts %} - -{% endblock %} diff --git a/src/judas_server/web/templates/login.html b/src/judas_server/web/templates/login.html deleted file mode 100644 index e5b1b11..0000000 --- a/src/judas_server/web/templates/login.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - judas - login page - - - -
    -
    -

    judas

    -
    -
    -
    -

    Login

    -
    - - -
    -
    - - {% if error %} -
    -

    Login failure

    -

    {{ error }}

    -
    - {% endif %} -
    -
    -
    -
    - - diff --git a/src/judas_server/web/templates/panel.html b/src/judas_server/web/templates/panel.html deleted file mode 100644 index 2582ef6..0000000 --- a/src/judas_server/web/templates/panel.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "base/base.html" %} - -{% block title %}panel{% endblock %} - -{% block content %} -
    - -
    -
    -{% endblock %} - -{% block scripts %} - -{% endblock %} diff --git a/src/judas_server/web/user.py b/src/judas_server/web/user.py deleted file mode 100644 index d26e40e..0000000 --- a/src/judas_server/web/user.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import annotations - -import flask_login - - -class User(flask_login.UserMixin): - """Represents a user for authentication purposes.""" - - def __init__(self, id: str) -> None: - super().__init__() - self.id = id - - def get_id(self) -> str: - """Return the unique identifier for the user.""" - return self.id - - def __str__(self) -> str: - return f"User(id={self.id})" - - def __repr__(self) -> str: - return f"User(id={self.id})" - - -def load_user(user_id): - if user_id == "admin": - return User("admin") - return None diff --git a/src/judas_server/web/web_server.py b/src/judas_server/web/web_server.py deleted file mode 100644 index 81ae471..0000000 --- a/src/judas_server/web/web_server.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import annotations - -import logging as lg -from typing import TYPE_CHECKING - -from flask import Flask -from flask_login import LoginManager -from flask_socketio import SocketIO - -from judas_server.web.user import load_user - -if TYPE_CHECKING: - from judas_server.backend import BackendServer - - -class JudasWebServer: - def __init__(self, backend: BackendServer, secret_key: str) -> None: - self.logger: lg.Logger = lg.getLogger( - f"{__name__}.{self.__class__.__name__}" - ) - self.logger.debug("Initializing JudasWebServer...") - - self.backend: BackendServer = backend - - self.app: Flask = Flask( - __name__, static_folder="static", template_folder="templates" - ) - self.app.secret_key = secret_key - - self.app.config["WEB_SERVER"] = self - self.app.config["BACKEND"] = self.backend - - # hard-code password - self.app.config["PASSWORD"] = "123" - - # extensions - self.login_manager: LoginManager = LoginManager() - - self.socketio: SocketIO = SocketIO(self.app, cors_allowed_origins="*") - - self.configure_extensions() - self.init_routes() - - def configure_extensions(self) -> None: - self.logger.debug("Configuring extensions...") - self.login_manager.init_app(self.app) - self.login_manager.user_loader(load_user) - self.login_manager.login_view = "auth.login" - - # TODO: add login page - - def init_routes(self) -> None: - self.logger.debug("Initializing routes...") - from judas_server.web.routes import ( - api, - auth_bp, - index_bp, - panel_bp, - client_details, - ) - - self.app.register_blueprint(index_bp) - self.app.register_blueprint(auth_bp) - self.app.register_blueprint(panel_bp) - self.app.register_blueprint(api.bp) - self.app.register_blueprint(client_details.bp) - api.emit_polled_data(self.app, self.socketio) - - def run( - self, host: str = "0.0.0.0", port: int = 5000, debug: bool = False - ) -> None: - self.logger.info(f"Starting web server on {host}:{port}...") - self.socketio.run(app=self.app, host=host, port=port, debug=debug) - self.logger.info("Server stopped.")