From 502e68f1aaaef7d6824830fb2e89368db65ba275 Mon Sep 17 00:00:00 2001 From: Emi Tatsuo Date: Sun, 22 Nov 2020 01:29:24 -0500 Subject: [PATCH] Updated the user management example to be more accessible --- examples/user_management.rs | 106 ++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 10 deletions(-) diff --git a/examples/user_management.rs b/examples/user_management.rs index 0f6c1aa..ab88f34 100644 --- a/examples/user_management.rs +++ b/examples/user_management.rs @@ -2,32 +2,118 @@ use anyhow::*; use log::LevelFilter; use northstar::{ GEMINI_PORT, + Document, Request, Response, Server, - user_management::UserManagementRoutes, + user_management::{ + User, + UserManagementRoutes, + }, }; #[tokio::main] +/// An ultra-simple demonstration of authentication. +/// +/// The user should be able to set a secret string that only they can see. They should be +/// able to change this at any time to any thing. Both the string and the user account +/// will persist across restarts. +/// +/// This method sets up and starts the server async fn main() -> Result<()> { + // Turn on logging env_logger::builder() .filter_module("northstar", LevelFilter::Debug) .init(); Server::bind(("0.0.0.0", GEMINI_PORT)) - .add_route("/", handle_request) + + // Add our main routes + .add_route("/", handle_main) + .add_route("/update", handle_update) + + // Add routes for handling user authentication .add_um_routes::("/") + + // Start the server .serve() .await } -/// An ultra-simple demonstration of simple authentication. +/// The landing page /// -/// 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. -async fn handle_request(_request: Request) -> Result { - Ok(Response::success_plain("Base handler")) +/// Displays the user's current secret string, or prompts the user to sign in if they +/// haven't. Includes links to update your string (`/update`) or your account +/// (`/account`). Even though we haven't added an explicit handler for `/account`, this +/// route is managed by northstar. +async fn handle_main(request: Request) -> Result { + + // Check to see if the user is signed in. If they are, we get a copy of their data + // (just a simple [`String`] for this demo, but this can be any serializable struct. + if let User::SignedIn(user) = request.user::()? { + + // If the user is signed in, render and return their page + let response = Document::new() + .add_text("Your personal secret string:") + .add_text(user.as_ref()) + .add_blank_line() + .add_link("/update", "Change your string") + .add_link("/account", "Update your account") + .into(); + Ok(response) + + } else { + + // If the user is not logged in, prompt them to go to /account + let response = Document::new() + .add_text("Please login to use this app.") + .add_blank_line() + .add_link("/account", "Login or create account") + .into(); + Ok(response) + + } +} + +/// The update endpoint +/// +/// Users can update their secret string here. Users who haven't logged in will be +/// promped to do so. +async fn handle_update(request: Request) -> Result { + + // Check if the user is signed in again + if let User::SignedIn(mut user) = request.user::()? { + + // If the user is logged in, check to see if they provided any input. If they + // have, we can set that input as their new string, otherwise we ask them for it + if let Some(string) = request.input() { + + // Update the users data + *user.as_mut() = string.to_owned(); + + // Render a response + let response = Document::new() + .add_text("String updated!") + .add_blank_line() + .add_link("/", "Back") + .into(); + Ok(response) + + } else { + + // Ask the user for some input + Ok(Response::input_lossy("Enter your new string")) + + } + } else { + + // The user isn't logged in, so we should ask them too + let response = Document::new() + .add_text("Please login to use this app.") + .add_blank_line() + .add_link("/account", "Login or create account") + .into(); + Ok(response) + + } }