9 Commits

7 changed files with 175 additions and 104 deletions

View File

@@ -4,14 +4,17 @@ import logging as lg
if __name__ == "__main__": if __name__ == "__main__":
from judas_server.web.web_server import JudasWebServer from judas_server.web.web_server import JudasWebServer
from judas_server.backend import BackendServer
lg.basicConfig( lg.basicConfig(
level=lg.DEBUG, level=lg.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
) )
server = JudasWebServer(secret_key="dildo") backend_server = BackendServer()
server.run(
web_server = JudasWebServer(backend=backend_server, secret_key="dildo")
web_server.run(
host="0.0.0.0", host="0.0.0.0",
port=5000, port=5000,
) )

View File

@@ -0,0 +1,3 @@
from .server import BackendServer
__all__ = ["BackendServer"]

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
from __future__ import annotations
from typing import Any
import logging as lg
import random as rn
import threading
import time
class BackendServer:
def __init__(self) -> None:
self.logger: lg.Logger = lg.getLogger(
f"{__name__}.{self.__class__.__name__}"
)
self.logger.debug("Initializing Server...")
# TODO: add socket logic here
self.clients: dict[str, dict[str, dict[str, Any]]] = {
"C_01": {
"one_time": {
"hostname": "mock-host",
"platform": "windows 11",
"cpu_info": "i7",
},
"polled": {"cpu_usage": 0, "mem_usage": 0},
"ondemand": {},
}
}
self.running: bool = False
def start_polling(self) -> None:
self.running = True
def _poll_loop(self) -> None:
while self.running:
for client in self.clients.values():
client["polled"]["cpu"] = round(rn.uniform(0, 100), 1)
client["polled"]["ram"] = round(rn.uniform(0, 100), 1)
time.sleep(1)
def get_client_data(
self, client_id: str
) -> dict[str, dict[str, Any]] | None:
return self.clients.get(client_id, None)

View File

@@ -1,36 +1,44 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>judas panel - details</title> <title>judas panel - details</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> <link
</head> rel="stylesheet"
<body> href="{{ url_for('static', filename='css/style.css') }}"
/>
</head>
<body>
<div id="wrapper"> <div id="wrapper">
<header> <header>
<h1><a href="{{ url_for('index.index') }}">judas</a></h1> <h1><a href="{{ url_for('index.index') }}">judas</a></h1>
<p><a class="button" href="{{ url_for('logout') }}">Logout</a></p> <p><a class="button" href="{{ url_for('logout') }}">Logout</a></p>
</header> </header>
<main> <main>
<div class="button-container"> <div class="button-container">
<p><a href="{{ url_for('panel') }}" class="link">Back to Panel</a></p> <p><a href="{{ url_for('panel') }}" class="link">Back to Panel</a></p>
<h2>{{ pc.id }}</h2> <h2>{{ pc.id }}</h2>
<p><a href="{{ url_for('stream', pc_id=pc.id) }}" class="link">View Stream</a></p> <p>
</div> <a href="{{ url_for('stream', pc_id=pc.id) }}" class="link"
<table class="center-table details-table"> >View Stream</a
<tbody> >
<tr> </p>
<td>Status</td> </div>
<td>{{ pc.status }}</td> <table class="center-table details-table">
</tr> <tbody>
<tr> <tr>
<td>Last Seen</td> <td>Status</td>
<td>{{ pc.last_seen }}</td> <td>{{ pc.status }}</td>
</tr> </tr>
</tbody> <tr>
</table> <td>Last Seen</td>
</main> <td>{{ pc.last_seen }}</td>
</tr>
</tbody>
</table>
</main>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,54 +1,54 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>judas</title> <title>judas</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head> </head>
<body> <body>
<div id="wrapper"> <div id="wrapper">
<header> <header>
<h1><a href="{{ url_for('index.index') }}">judas</a></h1> <h1><a href="{{ url_for('index.index') }}">judas</a></h1>
{% if logged %} {% if logged %}
<p><a class="button" href="{{ url_for('auth.logout') }}">Logout</a></p> <p><a class="button" href="{{ url_for('auth.logout') }}">Logout</a></p>
{% else %} {% else %}
<p><a class="button" href="{{ url_for('auth.login') }}">Login</a></p> <p><a class="button" href="{{ url_for('auth.login') }}">Login</a></p>
{% endif %} {% endif %}
</header> </header>
<main class="center"> <main class="center">
<div> <div>
<p>Welcome to</p> <p>Welcome to</p>
<h2 id="typing-text" style="font-size: 3rem;">judas</h2> <h2 id="typing-text" style="font-size: 3rem;">judas</h2>
<p>a remote PC fleet management system</p> <p>a remote PC fleet management system</p>
</div> </div>
<p style="color: #bf616a;"><strong>Notice:</strong> Please use this system responsibly and in accordance with all applicable laws and organizational policies.</p> <p style="color: #bf616a;"><strong>Notice:</strong> Please use this system responsibly and in accordance with all applicable laws and organizational policies.</p>
{% if logged %} {% if logged %}
<p><a class="button" href="{{ url_for('panel.panel') }}">Go to panel</a></p> <p><a class="button" href="{{ url_for('panel.panel') }}">Go to panel</a></p>
{% else %} {% else %}
<p>Please <a href="{{ url_for('auth.login')}}" class="link">log in</a> to manage your remote PCs.</p> <p>Please <a href="{{ url_for('auth.login')}}" class="link">log in</a> to manage your remote PCs.</p>
{% endif %} {% endif %}
</main> </main>
</div> </div>
<script> <script>
var i = 0; var i = 0;
var txt = document.getElementById("typing-text").innerHTML; var txt = document.getElementById("typing-text").innerHTML;
var minSpeed = 50; var minSpeed = 50;
var maxSpeed = 200; var maxSpeed = 200;
document.getElementById("typing-text").innerHTML = ""; document.getElementById("typing-text").innerHTML = "";
function typeWriter() { function typeWriter() {
if (i < txt.length) { if (i < txt.length) {
document.getElementById("typing-text").innerHTML += txt.charAt(i); document.getElementById("typing-text").innerHTML += txt.charAt(i);
i++; i++;
var randomDelay = Math.floor(Math.random() * (maxSpeed - minSpeed + 1)) + minSpeed; var randomDelay = Math.floor(Math.random() * (maxSpeed - minSpeed + 1)) + minSpeed;
setTimeout(typeWriter, randomDelay); setTimeout(typeWriter, randomDelay);
} }
} }
typeWriter(); typeWriter();
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,32 +1,32 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>judas - login page</title> <title>judas - login page</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head> </head>
<body> <body>
<div id="wrapper"> <div id="wrapper">
<header> <header>
<h1><a href="{{ url_for('index.index') }}">judas</a></h1> <h1><a href="{{ url_for('index.index') }}">judas</a></h1>
</header> </header>
<main> <main>
<h1>Login</h1> <h1>Login</h1>
<form method="post" class="center"> <form method="post" class="center">
<label for="password">Password:</label> <label for="password">Password:</label>
<input type="password" id="password" name="password" required autofocus> <input type="password" id="password" name="password" required autofocus>
<br> <br>
<br> <br>
<input type="submit" value="Login" class="button"> <input type="submit" value="Login" class="button">
{% if error %} {% if error %}
<div class="error-container"> <div class="error-container">
<h1>Login failure</h1> <h1>Login failure</h1>
<p>{{ error }}</p> <p>{{ error }}</p>
</div> </div>
{% endif %} {% endif %}
</form> </form>
</main> </main>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -3,30 +3,39 @@
from __future__ import annotations from __future__ import annotations
import logging as lg import logging as lg
from typing import TYPE_CHECKING
from flask import Flask from flask import Flask
from flask_login import LoginManager from flask_login import LoginManager
from judas_server.web.user import load_user from judas_server.web.user import load_user
if TYPE_CHECKING:
from judas_server.backend import BackendServer
class JudasWebServer: class JudasWebServer:
def __init__(self, secret_key: str) -> None: def __init__(self, backend: BackendServer, secret_key: str) -> None:
self.logger: lg.Logger = lg.getLogger( self.logger: lg.Logger = lg.getLogger(
f"{__name__}.{self.__class__.__name__}" f"{__name__}.{self.__class__.__name__}"
) )
self.logger.debug("Initializing JudasWebServer...") self.logger.debug("Initializing JudasWebServer...")
self.backend: BackendServer = backend
self.app: Flask = Flask( self.app: Flask = Flask(
__name__, static_folder="static", template_folder="templates" __name__, static_folder="static", template_folder="templates"
) )
self.app.secret_key = secret_key self.app.secret_key = secret_key
self.app.config["WEB_SERVER"] = self
self.app.config["BACKEND"] = self.backend
# hard-code password # hard-code password
self.app.config["PASSWORD"] = "123" self.app.config["PASSWORD"] = "123"
# extensions # extensions
self.login_manager: LoginManager = LoginManager() self.login_manager: LoginManager = LoginManager()
self.app.config["LoginManager"] = self.login_manager
self.configure_extensions() self.configure_extensions()
self.init_routes() self.init_routes()