summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2023-12-11 11:24:37 +0000
committerLibravatar cel 🌸 <cel@blos.sm>2023-12-11 11:24:37 +0000
commit159b239aa2964f6c07438638b967746354376b2e (patch)
tree4b2b857c9d6ec11e3397e70cc77da51186728d55 /src
parent2407c1a4a55d17817b31f7ca5cac9d68b27f536c (diff)
downloadpinussy-159b239aa2964f6c07438638b967746354376b2e.tar.gz
pinussy-159b239aa2964f6c07438638b967746354376b2e.tar.bz2
pinussy-159b239aa2964f6c07438638b967746354376b2e.zip
implement log-in
Diffstat (limited to '')
-rw-r--r--src/main.rs96
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
}
}