diff options
Diffstat (limited to '')
| -rw-r--r-- | src/main.rs | 83 | 
1 files changed, 76 insertions, 7 deletions
| diff --git a/src/main.rs b/src/main.rs index eb7f0e8..c1520ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers};  use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, ResponseError};  use bcrypt::{hash, verify, DEFAULT_COST};  use serde::Deserialize; +use sqlx::postgres::PgDatabaseError;  use sqlx::{postgres::PgPoolOptions, Pool, Postgres};  use templates::statics::StaticFile; @@ -67,7 +68,7 @@ async fn home() -> HttpResponse {  #[get("/signup")]  async fn get_signup() -> HttpResponse { -    HttpResponse::Ok().body(render!(templates::signup_html).unwrap()) +    HttpResponse::Ok().body(render!(templates::signup_html, None).unwrap())  }  #[derive(Deserialize)] @@ -82,31 +83,78 @@ async fn post_signup(      form: web::Form<SignupForm>,  ) -> Result<HttpResponse> {      let password_hash = hash(&form.password, DEFAULT_COST)?; -    sqlx::query!( +    match sqlx::query!(          "insert into users(username, password) values ($1, $2)",          &form.username,          password_hash      )      .execute(&state.db) -    .await?; -    Ok(HttpResponse::Ok().body(render!(templates::signup_html).unwrap())) +    .await +    { +        Ok(_) => { +            return Ok(HttpResponse::Ok().body( +                render!( +                    templates::signup_html, +                    Some(Notification { +                        kind: NotificationKind::Info, +                        message: format!("you have successfully registered as {}", &form.username) +                    }) +                ) +                .unwrap(), +            )) +        } +        Err(e) => { +            match e { +                sqlx::Error::Database(e) => { +                    if e.is_unique_violation() { +                        return Ok(HttpResponse::Conflict().body( +                            render!( +                                templates::signup_html, +                                Some(Notification { +                                    kind: NotificationKind::Error, +                                    message: format!( +                                        "error: the username \"{}\" already exists", +                                        &form.username +                                    ) +                                }) +                            ) +                            .unwrap(), +                        )); +                    } +                } +                // TODO: log error +                _ => {} +            } +            return Ok(HttpResponse::InternalServerError().body( +                render!( +                    templates::signup_html, +                    Some(Notification { +                        kind: NotificationKind::Error, +                        message: "there was an internal server error. please try again later." +                            .to_owned() +                    }) +                ) +                .unwrap(), +            )); +        } +    };  }  #[get("/login")]  async fn get_login() -> HttpResponse { -    HttpResponse::Ok().body(render!(templates::login_html).unwrap()) +    HttpResponse::Ok().body(render!(templates::login_html, None).unwrap())  }  #[derive(Deserialize)]  struct LoginForm {      username: String,      password: String, -    rememberme: bool, +    rememberme: Option<String>,  }  #[post("/login")]  async fn post_login(form: web::Form<LoginForm>) -> Result<HttpResponse> { -    Ok(HttpResponse::Ok().body(render!(templates::login_html).unwrap())) +    Ok(HttpResponse::Ok().body(render!(templates::login_html, None).unwrap()))  }  #[derive(sqlx::Type)] @@ -129,6 +177,27 @@ pub struct User {      admin: bool,  } +pub enum NotificationKind { +    Info, +    Warning, +    Error, +} + +impl std::fmt::Display for NotificationKind { +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +        match self { +            NotificationKind::Info => f.write_str("info"), +            NotificationKind::Warning => f.write_str("warning"), +            NotificationKind::Error => f.write_str("error"), +        } +    } +} + +pub struct Notification { +    kind: NotificationKind, +    message: String, +} +  #[get("/users")]  async fn get_users(state: web::Data<Pinussy>) -> Result<HttpResponse> {      let users: Vec<User> = sqlx::query_as("select * from users") | 
