From 9916770bd266e05b3a3ba87527a3d9f18105ce86 Mon Sep 17 00:00:00 2001 From: Emi Tatsuo Date: Sun, 22 Nov 2020 20:56:15 -0500 Subject: [PATCH] Added add_authenticated_input_route --- examples/user_management.rs | 34 ++++++++------------ src/user_management/routes.rs | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/examples/user_management.rs b/examples/user_management.rs index 964c660..3329b40 100644 --- a/examples/user_management.rs +++ b/examples/user_management.rs @@ -30,7 +30,7 @@ async fn main() -> Result<()> { // Add our main routes .add_authenticated_route("/", handle_main) - .add_authenticated_route("/update", handle_update) + .add_authenticated_input_route("/update", "Enter your new string:", handle_update) // Add routes for handling user authentication .add_um_routes::("/") @@ -64,28 +64,20 @@ async fn handle_main(_req: Request, user: RegisteredUser) -> Result) -> Result { +async fn handle_update(_request: Request, mut user: RegisteredUser, input: String) -> Result { - // 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() { + // The user has already been prompted to log in if they weren't and asked to give an + // input string, so all we need to do is... - // Update the users data - *user.as_mut() = string.to_owned(); + // Update the users data + *user.as_mut() = input; - // 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")) - - } + // Render a response + let response = Document::new() + .add_text("String updated!") + .add_blank_line() + .add_link("/", "Back") + .into(); + Ok(response) } diff --git a/src/user_management/routes.rs b/src/user_management/routes.rs index 2225cb1..11675a6 100644 --- a/src/user_management/routes.rs +++ b/src/user_management/routes.rs @@ -47,6 +47,38 @@ pub trait UserManagementRoutes: private::Sealed { UserData: Serialize + DeserializeOwned + 'static + Send + Sync, Handler: Clone + Send + Sync + 'static + Fn(Request, RegisteredUser) -> F, F: Send + Sync + 'static + Future>; + + /// Add a special route that requires users to be logged in AND takes input + /// + /// Like with [`add_authenticated_route()`](Self::add_authenticated_route()), this + /// prompts the user to log in if they haven't already, but additionally prompts the + /// user for input before running the handler with both the user object and the input + /// they provided. + /// + /// To a user, this might look something like this: + /// * Click a link to `/your/route` + /// * See a screen asking you to sign in or create an account + /// * Create a new account, and return to the app. + /// * Now, clicking the link shows the prompt provided. + /// * After entering some value, the user receives the response from the handler. + /// + /// For a user whose already logged in, this will just look like a normal input route, + /// where they enter some query and see a page. This method just takes the burden of + /// having to check if the user sent a query string and respond with an INPUT response + /// if not. + /// + /// To use this method, ensure that [`add_um_routes()`](Self::add_um_routes()) has + /// also been called. + fn add_authenticated_input_route( + self, + path: &'static str, + prompt: &'static str, + handler: Handler, + ) -> Self + where + UserData: Serialize + DeserializeOwned + 'static + Send + Sync, + Handler: Clone + Send + Sync + 'static + Fn(Request, RegisteredUser, String) -> F, + F: Send + Sync + 'static + Future>; } impl UserManagementRoutes for crate::Builder { @@ -91,6 +123,32 @@ impl UserManagementRoutes for crate::Builder { } }) } + + /// Add a special route that requires users to be logged in AND takes input + /// + /// See [`UserManagementRoutes::add_authenticated_input_route()`] + fn add_authenticated_input_route( + self, + path: &'static str, + prompt: &'static str, + handler: Handler, + ) -> Self + where + UserData: Serialize + DeserializeOwned + 'static + Send + Sync, + Handler: Clone + Send + Sync + 'static + Fn(Request, RegisteredUser, String) -> F, + F: Send + Sync + 'static + Future> + { + self.add_authenticated_route(path, move|request, user| { + let handler = handler.clone(); + async move { + if let Some(input) = request.input().map(str::to_owned) { + (handler.clone())(request, user, input).await + } else { + Response::input(prompt) + } + } + }) + } } async fn handle_base(request: Request, redirect: &'static str) -> Result {