app: add a welcome handler
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
d11357e5f2
commit
1968beaa0d
@ -11,6 +11,7 @@ import logging
|
|||||||
import json
|
import json
|
||||||
import traceback
|
import traceback
|
||||||
import ssl
|
import ssl
|
||||||
|
import pathlib
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import tornado
|
import tornado
|
||||||
import tornado.iostream
|
import tornado.iostream
|
||||||
@ -205,8 +206,10 @@ class MoonrakerApp:
|
|||||||
self.mutable_router = MutableRouter(self)
|
self.mutable_router = MutableRouter(self)
|
||||||
app_handlers: List[Any] = [
|
app_handlers: List[Any] = [
|
||||||
(AnyMatches(), self.mutable_router),
|
(AnyMatches(), self.mutable_router),
|
||||||
|
(r"/", WelcomeHandler),
|
||||||
(r"/websocket", WebSocket),
|
(r"/websocket", WebSocket),
|
||||||
(r"/server/redirect", RedirectHandler)]
|
(r"/server/redirect", RedirectHandler)
|
||||||
|
]
|
||||||
self.app = tornado.web.Application(app_handlers, **app_args)
|
self.app = tornado.web.Application(app_handlers, **app_args)
|
||||||
self.get_handler_delegate = self.app.get_handler_delegate
|
self.get_handler_delegate = self.app.get_handler_delegate
|
||||||
|
|
||||||
@ -932,3 +935,83 @@ class RedirectHandler(AuthorizedRequestHandler):
|
|||||||
raise tornado.web.HTTPError(
|
raise tornado.web.HTTPError(
|
||||||
400, f"Unauthorized URL redirect: {url}")
|
400, f"Unauthorized URL redirect: {url}")
|
||||||
self.redirect(url)
|
self.redirect(url)
|
||||||
|
|
||||||
|
class WelcomeHandler(tornado.web.RequestHandler):
|
||||||
|
def initialize(self) -> None:
|
||||||
|
self.server: Server = self.settings['server']
|
||||||
|
|
||||||
|
def get(self) -> None:
|
||||||
|
summary: List[str] = []
|
||||||
|
auth: AuthComp = self.server.lookup_component("authorization", None)
|
||||||
|
if auth is not None:
|
||||||
|
try:
|
||||||
|
user = auth.check_authorized(self.request)
|
||||||
|
except tornado.web.HTTPError:
|
||||||
|
authorized = False
|
||||||
|
else:
|
||||||
|
authorized = True
|
||||||
|
if authorized:
|
||||||
|
summary.append(
|
||||||
|
"Your device is authorized to access Moonraker's API."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
summary.append(
|
||||||
|
"Your device is not authorized to access Moonraker's API. "
|
||||||
|
"This is normal if you intend to use API Key "
|
||||||
|
"authentication or log in as an authenticated user. "
|
||||||
|
"Otherwise you need to add your IP address to the "
|
||||||
|
"'trusted_clients' option in the [authorization] section "
|
||||||
|
"of moonraker.conf."
|
||||||
|
)
|
||||||
|
cors_enabled = auth.cors_enabled()
|
||||||
|
if cors_enabled:
|
||||||
|
summary.append(
|
||||||
|
"CORS is enabled. Cross origin requests will be allowed "
|
||||||
|
"for origins that match one of the patterns specified in "
|
||||||
|
"the 'cors_domain' option of the [authorization] section."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
summary.append(
|
||||||
|
"All cross origin requests will be blocked by the browser. "
|
||||||
|
"The 'cors_domains' option in [authorization] must be "
|
||||||
|
"configured to enable CORS."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
authorized = True
|
||||||
|
cors_enabled = False
|
||||||
|
summary.append(
|
||||||
|
"The [authorization] component is not enabled in "
|
||||||
|
"moonraker.conf. All connections will be considered trusted."
|
||||||
|
)
|
||||||
|
summary.append(
|
||||||
|
"All cross origin requests will be blocked by the browser. "
|
||||||
|
"The [authorization] section in moonraker.conf must be "
|
||||||
|
"configured to enable CORS."
|
||||||
|
)
|
||||||
|
kstate = self.server.get_klippy_state()
|
||||||
|
if kstate != "disconnected":
|
||||||
|
kinfo = self.server.get_klippy_info()
|
||||||
|
kmsg = kinfo.get("state_message", kstate)
|
||||||
|
summary.append(f"Klipper reports {kmsg.lower()}")
|
||||||
|
else:
|
||||||
|
summary.append(
|
||||||
|
"Moonraker is not currently connected to Klipper. Make sure "
|
||||||
|
"that the klipper service has successfully started and that "
|
||||||
|
"its unix is enabled."
|
||||||
|
)
|
||||||
|
wsm: WebsocketManager = self.server.lookup_component("websockets")
|
||||||
|
context: Dict[str, Any] = {
|
||||||
|
"ip_address": self.request.remote_ip,
|
||||||
|
"authorized": authorized,
|
||||||
|
"cors_enabled": cors_enabled,
|
||||||
|
"version": self.server.get_app_args()["software_version"],
|
||||||
|
"ws_count": wsm.get_count(),
|
||||||
|
"klippy_state": kstate,
|
||||||
|
"warnings": self.server.get_warnings(),
|
||||||
|
"summary": summary
|
||||||
|
}
|
||||||
|
self.render("welcome.html", **context)
|
||||||
|
|
||||||
|
def get_template_path(self) -> Optional[str]:
|
||||||
|
tpath = pathlib.Path(__file__).parent.joinpath("assets")
|
||||||
|
return str(tpath)
|
||||||
|
180
moonraker/assets/welcome.html
Normal file
180
moonraker/assets/welcome.html
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Moonraker {{ version }}</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: rgb(48, 48, 48);
|
||||||
|
color: rgb(230, 230, 230);
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.nav-bar {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.nav-bar a {
|
||||||
|
float: right;
|
||||||
|
text-align: center;
|
||||||
|
padding: .5em .75em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgb(230, 230, 230);
|
||||||
|
}
|
||||||
|
.intro {
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin-top: 7rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
.intro h1 {
|
||||||
|
font-size: 2.2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 80%;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: center;
|
||||||
|
column-gap: 1.5rem;
|
||||||
|
row-gap: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background:none;
|
||||||
|
border: 0px;
|
||||||
|
border-radius: .75rem;
|
||||||
|
width: 25rem;
|
||||||
|
}
|
||||||
|
.container h1 {
|
||||||
|
background-color: #225353;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 2.2rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
height: 2.2rem;
|
||||||
|
margin: 0;
|
||||||
|
border-top-left-radius: .75rem;
|
||||||
|
border-top-right-radius: .75rem;
|
||||||
|
}
|
||||||
|
.container .content{
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
border-bottom-left-radius: .75rem;
|
||||||
|
border-bottom-right-radius: .75rem;
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
|
.container .entry {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container .entry:not(:last-child) {
|
||||||
|
margin-bottom: .4rem;
|
||||||
|
}
|
||||||
|
.container .value {
|
||||||
|
float: right;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.container ul {
|
||||||
|
margin: 0px;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
.container li:not(:last-child) {
|
||||||
|
margin-bottom: .4rem;
|
||||||
|
}
|
||||||
|
.messages {
|
||||||
|
margin-top: 2rem;
|
||||||
|
width: 51.5rem;
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
|
.warning h1 {
|
||||||
|
animation: glow 1s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glow {
|
||||||
|
from {
|
||||||
|
background-color: #225353;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: rgb(160, 64, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<div class="nav-bar">
|
||||||
|
<a href="https://github.com/Arksine/moonraker">GitHub</a>
|
||||||
|
<a href="https://moonraker.readthedocs.io">Documentation</a>
|
||||||
|
</div>
|
||||||
|
<div class="intro">
|
||||||
|
<h1>Welcome to Moonraker</h1>
|
||||||
|
<p>You may have intended
|
||||||
|
to navigate to one of Moonraker's front ends, if so check
|
||||||
|
that you entered the correct port in the address bar.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="status">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Authorization</h1>
|
||||||
|
<div class="content">
|
||||||
|
<div class="entry">
|
||||||
|
Request IP:
|
||||||
|
<div class="value">{{ ip_address }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="entry">
|
||||||
|
Trusted:
|
||||||
|
<div class="value">{{ authorized}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="entry">
|
||||||
|
CORS Enabled:
|
||||||
|
<div class="value">{{ cors_enabled }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Status</h1>
|
||||||
|
<div class="content">
|
||||||
|
<div class="entry">
|
||||||
|
Version:
|
||||||
|
<div class="value">{{ version }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="entry">
|
||||||
|
Websocket Count:
|
||||||
|
<div class="value">{{ ws_count }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="entry">
|
||||||
|
Klipper State:
|
||||||
|
<div class="value">{{ klippy_state }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if summary %}
|
||||||
|
<div class="container messages">
|
||||||
|
<h1>Summary</h1>
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
{% for item in summary %}
|
||||||
|
<li>{{ item }}</li>
|
||||||
|
{% end %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% end %}
|
||||||
|
{% if warnings %}
|
||||||
|
<div class="container messages warning">
|
||||||
|
<h1>Warnings</h1>
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
{% for warn in warnings %}
|
||||||
|
<li>{{ warn }}</li>
|
||||||
|
{% end %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% end %}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user