diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/src/main.rs b/src/main.rs index c1520ed..2736c5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,16 @@ mod actix_ructe; use std::time::{Duration, SystemTime}; +use actix_session::storage::CookieSessionStore; +use actix_session::{Session, SessionGetError, SessionInsertError, SessionMiddleware}; use actix_web::body::{BoxBody, EitherBody, MessageBody}; +use actix_web::cookie::time::Error; +use actix_web::cookie::Key; use actix_web::dev::ServiceResponse; +use actix_web::http::header::LOCATION; use actix_web::http::{header, StatusCode}; use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; +use actix_web::web::Redirect; use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, ResponseError}; use bcrypt::{hash, verify, DEFAULT_COST}; use serde::Deserialize; @@ -37,6 +43,11 @@ async fn main() -> std::io::Result<()> { HttpServer::new(move || { App::new() + .wrap(SessionMiddleware::new( + // TODO: postgres session store + CookieSessionStore::default(), + Key::generate(), + )) .wrap( ErrorHandlers::new() .handler(StatusCode::NOT_FOUND, render_404) @@ -45,6 +56,7 @@ async fn main() -> std::io::Result<()> { .app_data(web::Data::new(pinussy.clone())) .service(web::resource("/static/{filename}").to(static_file)) .service(home) + // .service(home_auth) .service(get_login) .service(post_login) .service(get_signup) @@ -62,8 +74,12 @@ async fn main() -> std::io::Result<()> { } #[get("/")] -async fn home() -> HttpResponse { - HttpResponse::Ok().body("Hello world!") +async fn home(session: Session) -> Result<HttpResponse> { + if let Some(user_id) = session.get::<i32>("user_id")? { + return Ok(HttpResponse::Ok().body(format!("you are logged in as {}", user_id))); + } else { + return Ok(HttpResponse::Ok().body("Hello world!")); + } } #[get("/signup")] @@ -153,8 +169,63 @@ struct LoginForm { } #[post("/login")] -async fn post_login(form: web::Form<LoginForm>) -> Result<HttpResponse> { - Ok(HttpResponse::Ok().body(render!(templates::login_html, None).unwrap())) +async fn post_login( + state: web::Data<Pinussy>, + session: Session, + form: web::Form<SignupForm>, +) -> Result<HttpResponse> { + match sqlx::query!( + "select id, password from users where username = $1", + &form.username + ) + .fetch_one(&state.db) + .await + { + Ok(user) => { + let password_hash: String = user.password; + if verify(&form.password, &password_hash)? { + session.insert("user_id", user.id)?; + return Ok(HttpResponse::SeeOther() + .insert_header((LOCATION, "/")) + .finish()); + } else { + return Ok(HttpResponse::Unauthorized().body( + render!( + templates::login_html, + Some(Notification { + kind: NotificationKind::Error, + message: "that password is incorrect".to_owned() + }) + ) + .unwrap(), + )); + } + } + Err(sqlx::Error::RowNotFound) => { + return Ok(HttpResponse::NotFound().body( + render!( + templates::login_html, + Some(Notification { + kind: NotificationKind::Error, + message: format!("the user \"{}\" does not exist", &form.username) + }) + ) + .unwrap(), + )); + } + Err(_) => { + return Ok(HttpResponse::InternalServerError().body( + render!( + templates::login_html, + Some(Notification { + kind: NotificationKind::Error, + message: "internal server error. please try again later".to_owned() + }) + ) + .unwrap(), + )); + } + } } #[derive(sqlx::Type)] @@ -203,6 +274,7 @@ async fn get_users(state: web::Data<Pinussy>) -> Result<HttpResponse> { let users: Vec<User> = sqlx::query_as("select * from users") .fetch_all(&state.db) .await + // TODO: no unwrap .unwrap(); println!("lol"); Ok(HttpResponse::Ok().body(render!(templates::users_html, users).unwrap())) @@ -258,9 +330,23 @@ fn error_response( #[derive(Debug)] enum PinussyError { Database(sqlx::Error), + SessionInsertError, + SessionGetError, Bcrypt, } +impl From<SessionInsertError> for PinussyError { + fn from(_: SessionInsertError) -> Self { + Self::SessionInsertError + } +} + +impl From<SessionGetError> for PinussyError { + fn from(_: SessionGetError) -> Self { + Self::SessionGetError + } +} + impl From<sqlx::Error> for PinussyError { fn from(e: sqlx::Error) -> Self { Self::Database(e) @@ -268,7 +354,7 @@ impl From<sqlx::Error> for PinussyError { } impl From<bcrypt::BcryptError> for PinussyError { - fn from(e: bcrypt::BcryptError) -> Self { + fn from(_: bcrypt::BcryptError) -> Self { Self::Bcrypt } } |