feat(server): add error feedback to signup form
							parent
							
								
									4902f4d1fe
								
							
						
					
					
						commit
						5017bfb710
					
				| 
						 | 
					@ -195,6 +195,7 @@ async fn get_signup(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJ
 | 
				
			||||||
        Redirect::to("/").into_response()
 | 
					        Redirect::to("/").into_response()
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        View::Signup {
 | 
					        View::Signup {
 | 
				
			||||||
 | 
					            username: None,
 | 
				
			||||||
            username_available: true,
 | 
					            username_available: true,
 | 
				
			||||||
            passwords_match: true,
 | 
					            passwords_match: true,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -207,10 +208,13 @@ async fn get_signup(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJ
 | 
				
			||||||
async fn post_signup(
 | 
					async fn post_signup(
 | 
				
			||||||
    State(ctx): State<Context>,
 | 
					    State(ctx): State<Context>,
 | 
				
			||||||
    jar: CookieJar,
 | 
					    jar: CookieJar,
 | 
				
			||||||
 | 
					    headers: HeaderMap,
 | 
				
			||||||
    user_agent: Option<TypedHeader<UserAgent>>,
 | 
					    user_agent: Option<TypedHeader<UserAgent>>,
 | 
				
			||||||
    Form(signup): Form<SignupForm>,
 | 
					    Form(signup): Form<SignupForm>,
 | 
				
			||||||
) -> AppResult<Response> {
 | 
					) -> AppResult<Response> {
 | 
				
			||||||
    if signup.validate(&ctx)?.valid() {
 | 
					    let validation = signup.validate(&ctx)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if validation.valid() {
 | 
				
			||||||
        // Create the user and log them in
 | 
					        // Create the user and log them in
 | 
				
			||||||
        match tokio::task::spawn_blocking(move || {
 | 
					        match tokio::task::spawn_blocking(move || {
 | 
				
			||||||
            let user = ctx.store.create_user(&signup.username, &signup.password)?;
 | 
					            let user = ctx.store.create_user(&signup.username, &signup.password)?;
 | 
				
			||||||
| 
						 | 
					@ -238,6 +242,13 @@ async fn post_signup(
 | 
				
			||||||
            Err(err) => Err(AppError::from(err)),
 | 
					            Err(err) => Err(AppError::from(err)),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        todo!("return form with error messages")
 | 
					        Ok(View::Signup {
 | 
				
			||||||
 | 
					            username: Some(signup.username),
 | 
				
			||||||
 | 
					            username_available: validation.username_available,
 | 
				
			||||||
 | 
					            passwords_match: validation.passwords_match,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        .page(&headers)
 | 
				
			||||||
 | 
					        .response(&ctx.tera)
 | 
				
			||||||
 | 
					        .into_response())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,7 @@ pub fn initialize_tera() -> tera::Result<tera::Tera> {
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        (
 | 
					        (
 | 
				
			||||||
            View::Signup {
 | 
					            View::Signup {
 | 
				
			||||||
 | 
					                username: None,
 | 
				
			||||||
                username_available: true,
 | 
					                username_available: true,
 | 
				
			||||||
                passwords_match: true,
 | 
					                passwords_match: true,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,34 @@
 | 
				
			||||||
<article>
 | 
					<article>
 | 
				
			||||||
    <form hx-post hx-target="#inner">
 | 
					    <form hx-post hx-target="#inner">
 | 
				
			||||||
        <label for="username">Username:</label>
 | 
					        <label for="username">Username:</label>
 | 
				
			||||||
        <input type="text" id="username" name="username">
 | 
					        <input
 | 
				
			||||||
 | 
					            type="text"
 | 
				
			||||||
 | 
					            id="username"
 | 
				
			||||||
 | 
					            name="username"
 | 
				
			||||||
 | 
					            value="{{ username }}"
 | 
				
			||||||
 | 
					            {% if not username_available %}
 | 
				
			||||||
 | 
					            aria-invalid="true"
 | 
				
			||||||
 | 
					            aria-describedby="username-helper"
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					        {% if not username_available %}
 | 
				
			||||||
 | 
					        <small id="username-helper">Username not available</small>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
        <label for="password">Password:</label>
 | 
					        <label for="password">Password:</label>
 | 
				
			||||||
        <input type="password" id="password" name="password">
 | 
					        <input type="password" id="password" name="password">
 | 
				
			||||||
        <label for="password_confirm">Confirm password:</label>
 | 
					        <label for="password_confirm">Confirm password:</label>
 | 
				
			||||||
        <input type="password" id="password_confirm" name="password_confirm">
 | 
					        <input
 | 
				
			||||||
 | 
					            type="password" 
 | 
				
			||||||
 | 
					            id="password_confirm"
 | 
				
			||||||
 | 
					            name="password_confirm"
 | 
				
			||||||
 | 
					            {% if not passwords_match %}
 | 
				
			||||||
 | 
					            aria-invalid="true"
 | 
				
			||||||
 | 
					            aria-describedby="password-helper"
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					        {% if not passwords_match %}
 | 
				
			||||||
 | 
					        <small id="password-helper">Passwords don't match</small>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
        <input type="submit" value="Sign Up">
 | 
					        <input type="submit" value="Sign Up">
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
</article>
 | 
					</article>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ pub enum View {
 | 
				
			||||||
    Sessions(Vec<gpodder::Session>, i64, Option<Query>),
 | 
					    Sessions(Vec<gpodder::Session>, i64, Option<Query>),
 | 
				
			||||||
    Users(Vec<gpodder::User>, i64, Option<Query>),
 | 
					    Users(Vec<gpodder::User>, i64, Option<Query>),
 | 
				
			||||||
    Signup {
 | 
					    Signup {
 | 
				
			||||||
 | 
					        username: Option<String>,
 | 
				
			||||||
        username_available: bool,
 | 
					        username_available: bool,
 | 
				
			||||||
        passwords_match: bool,
 | 
					        passwords_match: bool,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					@ -67,9 +68,11 @@ impl Template for View {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Self::Signup {
 | 
					            Self::Signup {
 | 
				
			||||||
 | 
					                username,
 | 
				
			||||||
                username_available,
 | 
					                username_available,
 | 
				
			||||||
                passwords_match,
 | 
					                passwords_match,
 | 
				
			||||||
            } => {
 | 
					            } => {
 | 
				
			||||||
 | 
					                ctx.insert("username", &username);
 | 
				
			||||||
                ctx.insert("username_available", &username_available);
 | 
					                ctx.insert("username_available", &username_available);
 | 
				
			||||||
                ctx.insert("passwords_match", &passwords_match);
 | 
					                ctx.insert("passwords_match", &passwords_match);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue