Browse Source

Create route for retrieving a user, including their accounts.

Lee Morgan 1 year ago
parent
commit
e241a7495e
6 changed files with 59 additions and 31 deletions
  1. 2 17
      src/controllers/account.rs
  2. 16 12
      src/controllers/user.rs
  3. 4 1
      src/dto/user.rs
  4. 15 0
      src/models/account.rs
  5. 19 0
      src/models/user.rs
  6. 3 1
      src/routes/user.rs

+ 2 - 17
src/controllers/account.rs

@@ -1,7 +1,7 @@
 use actix_web::{post, web, HttpResponse, HttpRequest};
 use mongodb::Database;
 
-use crate::models::{account::Account, user::User};
+use crate::models::account::Account;
 use crate::auth::user_auth;
 use crate::app_error::AppError;
 use crate::dto;
@@ -16,20 +16,5 @@ pub async fn create_route(
     let account_collection = db.collection::<Account>("accounts");
     let account_id = Account::insert(&account_collection, body.into_inner(), user).await?;
     let account = Account::find_by_id(&account_collection, account_id).await?;
-    Ok(HttpResponse::Ok().json(response_account(account)))
-}
-
-fn validate_account_ownership(account: &Account, user: &User) -> Result<(), AppError>{
-    if user._id.as_ref() == Some(&account.user) {
-        Ok(())
-    } else {
-        Err(AppError::Auth)
-    }
-}
-
-fn response_account(account: Account) -> dto::account::ResponseAccount {
-    dto::account::ResponseAccount {
-        data: account.data,
-        created_at: account.created_at.timestamp_millis()
-    }
+    Ok(HttpResponse::Ok().json(account.response()))
 }

+ 16 - 12
src/controllers/user.rs

@@ -1,10 +1,13 @@
-use actix_web::{get, post, web, HttpResponse, cookie::Cookie};
+use actix_web::{get, post, web, HttpResponse, HttpRequest, cookie::Cookie};
 use mongodb::{bson::doc, Database, Collection};
-use crate::models::user::{User, NewUserInput};
 use regex::Regex;
+use serde_json::json;
+
+use crate::models::user::{User, NewUserInput};
+use crate::models::account::{Account};
 use crate::dto;
 use crate::app_error::AppError;
-use serde_json::json;
+use crate::auth::user_auth;
 
 #[post("/api/user")]
 pub async fn create_route(
@@ -29,7 +32,7 @@ pub async fn login_route(
     let user = User::find_by_email(&user_collection, &email).await?;
     validate_password(&user, &payload.password_hash, &payload.password_salt)?;
     let cookie = create_user_cookie(Some(user._id.unwrap().to_string()));
-    Ok(HttpResponse::Ok().cookie(cookie).json(response_user(user)))
+    Ok(HttpResponse::Ok().cookie(cookie).json(user.response(None)))
 }
 
 #[get("/api/user/logout")]
@@ -38,6 +41,15 @@ pub async fn logout_route() -> Result<HttpResponse, AppError> {
     Ok(HttpResponse::Ok().cookie(cookie).json(json!({"success": true})))
 }
 
+#[get("/api/user")]
+pub async fn get_route(db: web::Data<Database>, req: HttpRequest) -> Result<HttpResponse, AppError> {
+    let user = user_auth(&db, &req).await?;
+    let account_collection = db.collection::<Account>("accounts");
+    let accounts = Account::find_by_user(&account_collection, user._id.unwrap()).await?;
+    let response_accounts = accounts.into_iter().map(Account::response).collect();
+    Ok(HttpResponse::Ok().json(user.response(Some(response_accounts))))
+}
+
 fn valid_email(email: &str) -> Result<(), AppError> {
     let email_regex: Regex = Regex::new(r#"^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}(\.[0-9]{1,3}){3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$"#).unwrap();
 
@@ -74,11 +86,3 @@ fn create_user_cookie(id: Option<String>) -> Cookie<'static> {
         .http_only(true)
         .finish()
 }
-
-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.timestamp_millis()
-    }
-}

+ 4 - 1
src/dto/user.rs

@@ -1,5 +1,7 @@
 use serde::{Serialize, Deserialize};
 
+use crate::models::account::ResponseAccount;
+
 #[derive(Deserialize)]
 pub struct Login {
     pub email: String,
@@ -11,5 +13,6 @@ pub struct Login {
 pub struct ResponseUser {
     pub id: String,
     pub email: String,
-    pub created_at: i64
+    pub accounts: Option<Vec<ResponseAccount>>,
+    pub created_at: i64,
 }

+ 15 - 0
src/models/account.rs

@@ -16,6 +16,13 @@ pub struct Account {
     pub created_at: DateTime
 }
 
+#[derive(Serialize, Deserialize)]
+pub struct ResponseAccount {
+    pub id: String,
+    pub data: String,
+    pub created_at: i64
+}
+
 impl Account {
     pub async fn insert(collection: &Collection<Account>, input: CreateInput, user: User) -> Result<ObjectId, AppError> {
         let object_id = match user._id {
@@ -55,4 +62,12 @@ impl Account {
             Err(e) => Err(AppError::Database(e.into()))
         }
     }
+
+    pub fn response(self) -> ResponseAccount {
+        ResponseAccount {
+            id: self._id.unwrap().to_string(),
+            data: self.data.clone(),
+            created_at: self.created_at.timestamp_millis()
+        }
+    }
 }

+ 19 - 0
src/models/user.rs

@@ -1,7 +1,9 @@
 use serde::{Serialize, Deserialize};
 use bson::{oid::ObjectId, DateTime, doc};
 use mongodb::{Collection, error::Error};
+
 use crate::app_error::AppError;
+use crate::models::account::ResponseAccount;
 
 #[derive(Debug, Serialize, Deserialize)]
 pub struct User {
@@ -20,6 +22,14 @@ pub struct NewUserInput {
     pub password_salt: String
 }
 
+#[derive(Serialize)]
+pub struct ResponseUser {
+    id: String,
+    email: String,
+    created_at: i64,
+    accounts: Option<Vec<ResponseAccount>>
+}
+
 impl User {
     pub async fn insert(collection: &Collection<User>, input: NewUserInput) -> Result<(), Error> {
         let user = User {
@@ -51,4 +61,13 @@ impl User {
             Err(e) => Err(AppError::Database(e.into()))
         }
     }
+
+    pub fn response(self, accounts: Option<Vec<ResponseAccount>>) -> ResponseUser {
+        ResponseUser {
+            id: self._id.unwrap().to_string(),
+            email: self.email.clone(),
+            created_at: self.created_at.timestamp_millis(),
+            accounts: accounts
+        }
+    }
 }

+ 3 - 1
src/routes/user.rs

@@ -2,11 +2,13 @@ use actix_web::web;
 use crate::controllers::user::{
     create_route,
     login_route,
-    logout_route
+    logout_route,
+    get_route
 };
 
 pub fn config(cfg: &mut web::ServiceConfig) {
     cfg.service(create_route);
     cfg.service(login_route);
     cfg.service(logout_route);
+    cfg.service(get_route);
 }