Forráskód Böngészése

Create login route.

Lee Morgan 1 éve
szülő
commit
29a6c490de
6 módosított fájl, 84 hozzáadás és 2 törlés
  1. 19 0
      bruno/Suma/User/Login.bru
  2. 43 1
      src/controllers/user.rs
  3. 1 0
      src/dto/mod.rs
  4. 15 0
      src/dto/user.rs
  5. 1 0
      src/main.rs
  6. 5 1
      src/routes/user.rs

+ 19 - 0
bruno/Suma/User/Login.bru

@@ -0,0 +1,19 @@
+meta {
+  name: Login
+  type: http
+  seq: 2
+}
+
+post {
+  url: http://localhost:8000/api/user/login
+  body: json
+  auth: inherit
+}
+
+body:json {
+  {
+    "email": "lee@leemorgan.dev",
+    "password_hash": "leerobertmorgan",
+    "password_salt": "leerobertmorgan"
+  }
+}

+ 43 - 1
src/controllers/user.rs

@@ -1,8 +1,9 @@
-use actix_web::{post, web, HttpResponse, Responder, http::StatusCode};
+use actix_web::{post, web, HttpResponse, Responder, http::StatusCode, cookie::Cookie};
 use mongodb::{bson::doc, Database};
 use crate::models::user::{User, NewUserInput};
 use regex::Regex;
 use crate::http_error::http_error;
+use crate::dto;
 
 #[post("/api/user")]
 pub async fn create(
@@ -26,7 +27,48 @@ pub async fn create(
     match User::insert(&user_collection, payload.into_inner()).await {
         Ok(_) => HttpResponse::Ok().body("{'success': 'true'}"),
         Err(e) => {
+            eprintln!("{}", e);
             http_error(StatusCode::INTERNAL_SERVER_ERROR, "Failed to create user")
         }
     }
 }
+
+#[post("/api/user/login")]
+pub async fn login(
+    db: web::Data<Database>,
+    payload: web::Json<dto::user::Login>
+) -> impl Responder {
+    let user_collection = db.collection::<User>("users");
+    let email = payload.email.to_lowercase();
+
+    let user: User = match user_collection.find_one(doc!{"email": email}, None).await {
+        Ok(Some(u)) => u,
+        Ok(None) => return http_error(StatusCode::BAD_REQUEST, "User with this email doesn't exist"),
+        Err(_) => return http_error(StatusCode::INTERNAL_SERVER_ERROR, "Unable to retrieve user data")
+    };
+
+    if user.password_hash != payload.password_hash {
+        return http_error(StatusCode::BAD_REQUEST, "Invalid credentials");
+    }
+    if user.password_salt != payload.password_salt {
+        return http_error(StatusCode::BAD_REQUEST, "Invalid credentials");
+    }
+
+    let id = user._id.unwrap().to_string();
+    let cookie = Cookie::build("user", id)
+        .path("/")
+        .http_only(true)
+        .finish();
+
+    HttpResponse::Ok()
+        .cookie(cookie)
+        .json(response_user(user))
+}
+
+fn response_user(user: User) -> dto::user::ResponseUser {
+    dto::user::ResponseUser {
+        id: user._id.unwrap().to_string(),
+        email: user.email,
+        created_at: user.created_at.to_string()
+    }
+}

+ 1 - 0
src/dto/mod.rs

@@ -0,0 +1 @@
+pub mod user;

+ 15 - 0
src/dto/user.rs

@@ -0,0 +1,15 @@
+use serde::{Serialize, Deserialize};
+
+#[derive(Deserialize)]
+pub struct Login {
+    pub email: String,
+    pub password_hash: String,
+    pub password_salt: String
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct ResponseUser {
+    pub id: String,
+    pub email: String,
+    pub created_at: String
+}

+ 1 - 0
src/main.rs

@@ -6,6 +6,7 @@ mod routes;
 mod models;
 mod controllers;
 mod http_error;
+mod dto;
 
 pub static HTML: OnceLock<String> = OnceLock::new();
 

+ 5 - 1
src/routes/user.rs

@@ -1,6 +1,10 @@
 use actix_web::web;
-use crate::controllers::user::create;
+use crate::controllers::user::{
+    create,
+    login
+};
 
 pub fn config(cfg: &mut web::ServiceConfig) {
     cfg.service(create);
+    cfg.service(login);
 }