use anyhow::*; use futures_core::future::BoxFuture; use futures_util::FutureExt; use log::LevelFilter; use northstar::{ GEMINI_MIME, GEMINI_PORT, Request, Response, Server, user_management::{User, UserManagerError}, }; #[tokio::main] async fn main() -> Result<()> { env_logger::builder() .filter_module("northstar", LevelFilter::Debug) .init(); Server::bind(("0.0.0.0", GEMINI_PORT)) .add_route("/", handle_request) .serve() .await } /// An ultra-simple demonstration of simple authentication. /// /// If the user attempts to connect, they will be prompted to create a client certificate. /// Once they've made one, they'll be given the opportunity to create an account by /// selecting a username. They'll then get a message confirming their account creation. /// Any time this user visits the site in the future, they'll get a personalized welcome /// message. fn handle_request(request: Request) -> BoxFuture<'static, Result> { async move { Ok(match request.user::()? { User::Unauthenticated => { Response::client_certificate_required() }, User::NotSignedIn(user) => { if let Some(username) = request.input() { match user.register::(username.to_owned()) { Ok(_user) => Response::success(&GEMINI_MIME) .with_body("Your account has been created!\n=>/ Begin"), Err(UserManagerError::UsernameNotUnique) => Response::input_lossy("That username is taken. Try again"), Err(e) => panic!("Unexpected error: {}", e), } } else { Response::input_lossy("Please pick a username") } }, User::SignedIn(mut user) => { if request.path_segments()[0].eq("push") { // User connecting to /push if let Some(push) = request.input() { user.as_mut().push_str(push); user.save()?; } else { return Ok(Response::input_lossy("Enter a string to push")); } } Response::success(&GEMINI_MIME) .with_body(format!("Your current string: {}\n=> /push Push", user.as_ref())) } }) }.boxed() }