added ppc server and mize run external subcommands

This commit is contained in:
Sebastian Moser
2026-09-30 09:37:21 +02:00
parent e96e93a5a0
commit c19de1ed84
9 changed files with 497 additions and 55 deletions

View File

@@ -41,6 +41,13 @@ chrono-tz = { version = "0.10.4", default-features = false }
url = "2.5.8"
serenity = { version = "0.12.5", optional = true }
matrix-sdk = "0.18.0"
axum = { version = "0.8.9", optional = true }
dioxus-ssr = { version = "0.7.10", optional = true }
axum-oidc = { version = "=1.0.0-dev-1", optional = true }
tower = { version = "0.5.3", optional = true }
tower-sessions = { version = "0.15.0", optional = true }
tower-http = { version = "0.7.1", optional = true, features = [ "cors", "trace" ] }
[features]
@@ -52,6 +59,6 @@ target-js = [ "mize/target-js", "spacetimedb-sdk/browser", "wasm-bindgen", "wasm
target-obsidian = [ "target-js" ]
desktop = ["dioxus/desktop"]
client = []
server = []
server = [ "axum", "dioxus-ssr", "axum-oidc", "tower", "tower-sessions", "tower-http" ]
clap = ["dep:clap"]
serenity = ["dep:serenity"]

View File

@@ -1,8 +1,19 @@
use dioxus::prelude::*;
use axum::response::Html;
pub fn main_page() -> Html<String> {
let html_output = dioxus_ssr::render_element(rsx! {
div {
h1 { "Hello from Dioxus SSR!" }
p { "This was rendered on the server and sent via Axum." }
}
});
pub fn main_page() -> Element {
Html(html_output)
}
pub fn main_page_element() -> Element {
rsx! {
"hello world"
div {

View File

@@ -1,4 +1,9 @@
use std::str::FromStr;
use clap::Command;
use dioxus::prelude::*;
use mize::Mize;
use mize::MizeResult;
pub mod server;
pub mod main_page;
pub use main_page::main_page;

145
marts/src/ppc/server.rs Normal file
View File

@@ -0,0 +1,145 @@
use std::str::FromStr;
use mize::{Mize, MizeError, MizeResult, mize_err};
use axum::response::Html;
use serde_json::json;
use serde_json::Value;
use axum::{
Json,
Router,
error_handling::HandleErrorLayer,
http::Uri,
response::IntoResponse,
routing::{any, get},
};
use axum_oidc::handle_oidc_redirect;
use axum_oidc::{
EmptyAdditionalClaims, OidcAuthLayer, OidcClaims, OidcClient, OidcLoginLayer,
OidcRpInitiatedLogout, error::MiddlewareError,
};
use openidconnect::Scope;
use openidconnect::{ClientId, ClientSecret, IssuerUrl};
use tower::ServiceBuilder;
use tower_sessions::{
Expiry, MemoryStore, SessionManagerLayer,
cookie::{SameSite, time::Duration},
};
pub fn part_ppc_server(mize: &mut Mize) -> MizeResult<()> {
mize.add_name_only_part("ppc.server");
let mut mize_clone = mize.clone();
mize.spawn_async("ppc.server_runner", start_server(mize_clone));
Ok(())
}
pub async fn start_server(mut mize: Mize) -> MizeResult<()> {
dioxus::logger::initialize_default();
let issuer = mize.get_config("auth.issuer")?.value_string()?;
let client_id = mize.get_config("auth.client_id")?.value_string()?;
let client_secret = mize.get_config("auth.client_secret")?.value_string()?;
let url = mize.get_config("web.url")?.value_string()?;
let redirect_url = format!("{url}/oidc");
let session_store = MemoryStore::default();
let session_layer = SessionManagerLayer::new(session_store)
.with_secure(false)
.with_same_site(SameSite::Lax)
.with_expiry(Expiry::OnInactivity(Duration::seconds(120)));
let oidc_login_service = ServiceBuilder::new()
.layer(HandleErrorLayer::new(|e: MiddlewareError| async {
dbg!(&e);
e.into_response()
}))
.layer(OidcLoginLayer::<EmptyAdditionalClaims>::new());
let oidc_client = OidcClient::<EmptyAdditionalClaims>::builder()
.with_default_http_client()
.with_redirect_url(Uri::from_str(redirect_url.as_str())?)
.with_client_id(ClientId::new(client_id))
.add_scope(Scope::new("profile".into()))
.add_scope(Scope::new("email".into()))
// Optional: add untrusted audiences. If the `aud` claim contains any of these audiences, the token is rejected.
//.add_untrusted_audience(Audience::new("123456789".to_string()))
.with_client_secret(ClientSecret::new(client_secret))
.discover(IssuerUrl::new(issuer.into()).expect("Invalid IssuerUrl"))
.await
.unwrap()
.build();
let oidc_auth_service = ServiceBuilder::new()
.layer(HandleErrorLayer::new(|e: MiddlewareError| async {
dbg!(&e);
e.into_response()
}))
.layer(OidcAuthLayer::new(oidc_client));
let app = Router::new()
.route("/foo", get(authenticated))
.route("/logout", get(logout))
.layer(oidc_login_service)
.route("/bar", get(maybe_authenticated))
.route("/oidc", any(handle_oidc_redirect::<EmptyAdditionalClaims>))
.layer(oidc_auth_service)
.layer(session_layer)
.layer(tower_http::trace::TraceLayer::new_for_http())
// not authenticated routes
.route("/", get(crate::ppc::main_page::main_page()))
// matrix .well-known
.route(
"/.well-known/matrix/client",
get(handle_matrix_client).layer(tower_http::cors::CorsLayer::permissive()),
)
.route(
"/.well-known/matrix/server",
get(handle_matrix_server),
);
tracing::info!("Running on http://localhost:3000");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service())
.await
.unwrap();
Ok(())
}
async fn authenticated(claims: OidcClaims<EmptyAdditionalClaims>) -> impl IntoResponse {
format!("Hello {}", claims.subject().as_str())
}
async fn maybe_authenticated(
claims: Result<OidcClaims<EmptyAdditionalClaims>, axum_oidc::error::ExtractorError>,
) -> impl IntoResponse {
if let Ok(claims) = claims {
format!(
"Hello {}! You are already logged in from another Handler.",
claims.subject().as_str()
)
} else {
"Hello anon!".to_string()
}
}
async fn logout(logout: OidcRpInitiatedLogout) -> impl IntoResponse {
logout.with_post_logout_redirect(Uri::from_static("https://localhost:3000"))
}
async fn handle_matrix_client() -> Json<Value> {
Json(json!({
"m.homeserver": {
"base_url": "https://matrix.ppc.social"
}
}))
}
async fn handle_matrix_server() -> Json<Value> {
Json(json!({
"m.server": "://ppc.social"
}))
}