refactor(admin): use warp instead
cargo devel CI / cargo CI (push) Successful in 2m3s Details

This commit is contained in:
Christoph J. Scherr 2024-09-07 18:03:29 +02:00
parent 8bd156b5fc
commit 73663d07ab
3 changed files with 60 additions and 48 deletions

View File

@ -16,10 +16,10 @@ anyhow = "1.0.86"
async-trait = "0.1.82" async-trait = "0.1.82"
clap = { version = "4.5.17", features = ["derive"] } clap = { version = "4.5.17", features = ["derive"] }
libpt = { version = "0.7.1", features = ["cli", "log"] } libpt = { version = "0.7.1", features = ["cli", "log"] }
minijinja = { version = "2.2.0", optional = true }
rand = "0.8.5" rand = "0.8.5"
serde = { version = "1.0.209", features = ["derive"] } serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.128" serde_json = "1.0.128"
tide = { version = "0.16.0", optional = true }
tokio = { version = "1.40.0", features = [ tokio = { version = "1.40.0", features = [
"macros", "macros",
"net", "net",
@ -28,7 +28,8 @@ tokio = { version = "1.40.0", features = [
"rt", "rt",
"sync", "sync",
] } ] }
warp = { version = "0.3.7", optional = true }
[features] [features]
default = ["admin-interface"] default = ["admin-interface"]
admin-interface = ["dep:tide"] admin-interface = ["dep:warp", "dep:minijinja"]

View File

@ -7,7 +7,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="author" content="{AUTHOR}">
<meta name="generator" content="Hugo 0.122.0"> <meta name="generator" content="Hugo 0.122.0">
<title>Starter Template · Bootstrap v5.3</title> <title>Starter Template · Bootstrap v5.3</title>
@ -21,19 +21,15 @@
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<!-- Favicons --> <!-- Favicons -->
<!-- <link rel="apple-touch-icon" href="/docs/5.3/assets/img/favicons/apple-touch-icon.png" sizes="180x180"> --> <link rel="icon" href="https://icons.getbootstrap.com/assets/icons/safe-fill.svg">
<!-- <link rel="icon" href="/docs/5.3/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png"> --> <meta name="theme-color" content="#712cf9">
<!-- <link rel="icon" href="/docs/5.3/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png"> -->
<!-- <link rel="manifest" href="/docs/5.3/assets/img/favicons/manifest.json"> -->
<!-- <link rel="mask-icon" href="/docs/5.3/assets/img/favicons/safari-pinned-tab.svg" color="#712cf9"> -->
<!-- <link rel="icon" href="/docs/5.3/assets/img/favicons/favicon.ico"> -->
<!-- <meta name="theme-color" content="#712cf9"> -->
<link rel="stylesheet" href="/styles.css"> <link rel="stylesheet" href="/styles.css">
</head> </head>
<body> <body>
<!-- All the svgs we use later -->
<svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="check2" viewBox="0 0 16 16"> <symbol id="check2" viewBox="0 0 16 16">
<path <path
@ -52,8 +48,19 @@
<path <path
d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" /> d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" />
</symbol> </symbol>
<symbol id="arrow-right-circle" viewBox="0 0 16 16">
<path
d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zM4.5 7.5a.5.5 0 0 0 0 1h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H4.5z" />
</symbol>
<symbol id="vault" viewBox="0 0 16 16">
<title>Bootstrap</title>
<path d="M9.778 9.414A2 2 0 1 1 6.95 6.586a2 2 0 0 1 2.828 2.828" />
<path
d="M2.5 0A1.5 1.5 0 0 0 1 1.5V3H.5a.5.5 0 0 0 0 1H1v3.5H.5a.5.5 0 0 0 0 1H1V12H.5a.5.5 0 0 0 0 1H1v1.5A1.5 1.5 0 0 0 2.5 16h12a1.5 1.5 0 0 0 1.5-1.5v-13A1.5 1.5 0 0 0 14.5 0zm3.036 4.464 1.09 1.09a3 3 0 0 1 3.476 0l1.09-1.09a.5.5 0 1 1 .707.708l-1.09 1.09c.74 1.037.74 2.44 0 3.476l1.09 1.09a.5.5 0 1 1-.707.708l-1.09-1.09a3 3 0 0 1-3.476 0l-1.09 1.09a.5.5 0 1 1-.708-.708l1.09-1.09a3 3 0 0 1 0-3.476l-1.09-1.09a.5.5 0 1 1 .708-.708M14 6.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 1 1 0" />
</symbol>
</svg> </svg>
<!-- theme switcher -->
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle"> <div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
<button class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center" id="bd-theme" type="button" <button class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center" id="bd-theme" type="button"
aria-expanded="false" data-bs-toggle="dropdown" aria-label="Toggle theme (auto)"> aria-expanded="false" data-bs-toggle="dropdown" aria-label="Toggle theme (auto)">
@ -102,27 +109,14 @@
</ul> </ul>
</div> </div>
<!-- basically everything but with some margin -->
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="arrow-right-circle" viewBox="0 0 16 16">
<path
d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zM4.5 7.5a.5.5 0 0 0 0 1h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H4.5z" />
</symbol>
<symbol id="bootstrap" viewBox="0 0 118 94">
<title>Bootstrap</title>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z">
</path>
</symbol>
</svg>
<div class="col-lg-8 mx-auto p-4 py-md-5"> <div class="col-lg-8 mx-auto p-4 py-md-5">
<header class="d-flex align-items-center pb-3 mb-5 border-bottom"> <header class="d-flex align-items-center pb-3 mb-5 border-bottom">
<a href="/" class="d-flex align-items-center text-body-emphasis text-decoration-none"> <a href="/" class="d-flex align-items-center text-body-emphasis text-decoration-none">
<svg class="bi me-2" width="40" height="32"> <svg class="bi me-2" width="40" height="32">
<use xlink:href="#bootstrap" /> <use xlink:href="#vault" />
</svg> </svg>
<span class="fs-4">Starter template</span> <span class="fs-4">{TITLE}</span>
</a> </a>
</header> </header>

View File

@ -1,41 +1,58 @@
use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
use libpt::log::warn;
use minijinja::context;
use minijinja::Environment;
use serde; use serde;
use tide::http::mime; use warp::Filter;
use tide::prelude::*;
use tide::Request;
use tide::Response;
use crate::config::Config; use crate::config::Config;
use crate::vault::VaultRef; use crate::vault::VaultRef;
#[derive(Clone)] #[derive(Clone)]
pub struct Interface { pub struct Service<'tp> {
vault: VaultRef, vault: VaultRef,
config: Config, config: Config,
env: Environment<'tp>,
}
impl<'tp> Service<'tp> {
fn new(vault: VaultRef, config: Config, env: Environment<'tp>) -> Arc<Self> {
Self { vault, config, env }.into()
}
} }
pub async fn serve(vault: VaultRef, config: Config) -> Result<()> { pub async fn serve(vault: VaultRef, config: Config) -> Result<()> {
let mut app = tide::with_state(Interface { vault, config }); let mut env = Environment::new();
app.at("/").get(overview); env.add_template("index", include_str!("../../data/www/admin.html"))?;
app.at("/styles.css").get(styles);
app.listen("127.0.0.1:8000").await?; let service = Service::new(vault, config, env);
let service2 = service.clone();
let routes = warp::path::end()
.map(move || service2.clone())
.and_then(overview);
warp::serve(routes)
.run(service.config.addr_admin.unwrap())
.await;
warn!("exited the admin interface");
Ok(()) Ok(())
} }
async fn overview(req: Request<Interface>) -> tide::Result { async fn overview(serv: Arc<Service<'_>>) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
let r = Response::builder(200) let r = serv
.content_type(mime::HTML) .env
.body(format!( .get_template("index")
include_str!("../../data/www/admin.html"), .unwrap()
TITLE = "Wooly-Vault" .render(context!(TITLE => "Wooly-Vault", AUTHOR => env!("CARGO_PKG_AUTHORS")))
)); .unwrap();
Ok(r.into()) Ok(Box::new(r))
} }
async fn styles(_req: Request<Interface>) -> tide::Result { async fn styles() -> Result<Box<dyn warp::Reply>, warp::Rejection> {
let r = Response::builder(200) let r = include_str!("../../data/www/styles.css").to_string();
.content_type(mime::CSS) Ok(Box::new(r))
.body(include_str!("../../data/www/styles.css"));
Ok(r.into())
} }