use actix_web::{get, post, web, HttpResponse}; use serde::Deserialize; use crate::notification::{Kind as NotificationKind, Notification}; use crate::templates; use crate::Pinussy; use crate::Result; use bcrypt::{hash, DEFAULT_COST}; #[get("/signup")] async fn get() -> HttpResponse { HttpResponse::Ok().body(render!(templates::signup_html, None).unwrap()) } #[derive(Deserialize)] struct SignupForm { username: String, password: String, } #[post("/signup")] async fn post(state: web::Data, form: web::Form) -> Result { let password_hash = hash(&form.password, DEFAULT_COST)?; match sqlx::query!( "insert into users(username, password) values ($1, $2)", &form.username, password_hash ) .execute(&state.db) .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(), )); } }; }