User registration

Already have an account? Sign in ← Back to home

Demo site — a fake email address is accepted. Privacy.

● ● ●
// Derive a form from the user model
#[form(schema = runique_users,
       fields = [username, email, password])]
pub struct RegisterForm;

#[async_trait]
impl RuniqueForm for RegisterForm {
    impl_form_access!(model);

    async fn clean(&mut self) -> Result<(), StrMap> {
        let mut errors = StrMap::new();
        if self.cleaned_string("username").unwrap_or_default().len() < 3 {
            errors.insert("username".into(), "3 characters minimum".into());
        }
        if !self.cleaned_string("email").unwrap_or_default().contains("@") {
            errors.insert("email".into(), "invalid email address".into());
        }
        if self.cleaned_string("password").unwrap_or_default().len() < 10 {
            errors.insert("password".into(), "10 characters minimum".into());
        }
        if errors.is_empty() { Ok(()) } else { Err(errors) }
    }
}
pub async fn registration_submit(mut request: Request) -> AppResult<Response> {
    let form: RegisterForm = request.form();
    let mut validated = match ValidationForm::try_new(form, &request).await {
        Ok(validated) => validated,
        Err(form) => {
            // GET, or submitted with errors: render the form again
            context_update!(request => { "registration_form" => &form });
            return request.render("auth/registration.html");
        }
    };
    match validated.save(&request.engine.db).await {
        Ok(_user) => {
            // The account stays pending until its owner follows the activation link
            success!(request.notices => "Account created! Check your email to activate it.");
            return Ok(Redirect::to("/login").into_response());
        }
        Err(err) => validated.database_error(&err),
    }
    context_update!(request => { "registration_form" => &*validated });
    request.render("auth/registration.html")
}
<form method="post" action="/registration">
    {# Full render — CSRF included automatically #}
    {% form.registration_form %}
    <button type="submit">Sign up</button>
</form>

{# Field-by-field render — CSRF always included automatically #}
<form method="post" action="/registration">
    {% form.registration_form.username %}
    {% form.registration_form.email %}
    {% form.registration_form.password %}
    <button type="submit">Sign up</button>
</form>