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 traceback
|
||||
import ssl
|
||||
import pathlib
|
||||
import urllib.parse
|
||||
import tornado
|
||||
import tornado.iostream
|
||||
@ -205,8 +206,10 @@ class MoonrakerApp:
|
||||
self.mutable_router = MutableRouter(self)
|
||||
app_handlers: List[Any] = [
|
||||
(AnyMatches(), self.mutable_router),
|
||||
(r"/", WelcomeHandler),
|
||||
(r"/websocket", WebSocket),
|
||||
(r"/server/redirect", RedirectHandler)]
|
||||
(r"/server/redirect", RedirectHandler)
|
||||
]
|
||||
self.app = tornado.web.Application(app_handlers, **app_args)
|
||||
self.get_handler_delegate = self.app.get_handler_delegate
|
||||
|
||||
@ -932,3 +935,83 @@ class RedirectHandler(AuthorizedRequestHandler):
|
||||
raise tornado.web.HTTPError(
|
||||
400, f"Unauthorized URL 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