瀏覽代碼

Create route for creating a new account.

Lee Morgan 1 年之前
父節點
當前提交
1e9ba9d240
共有 8 個文件被更改,包括 106 次插入17 次删除
  1. 17 0
      bruno/Suma/Account/Create.bru
  2. 8 0
      bruno/Suma/Account/folder.bru
  3. 7 4
      src/auth.rs
  4. 21 4
      src/controllers/account.rs
  5. 7 2
      src/dto/account.rs
  6. 40 2
      src/models/account.rs
  7. 4 3
      src/models/user.rs
  8. 2 2
      src/routes/account.rs

+ 17 - 0
bruno/Suma/Account/Create.bru

@@ -0,0 +1,17 @@
+meta {
+  name: Create
+  type: http
+  seq: 1
+}
+
+post {
+  url: http://localhost:8000/api/account
+  body: json
+  auth: inherit
+}
+
+body:json {
+  {
+    "data": "Something here"
+  }
+}

+ 8 - 0
bruno/Suma/Account/folder.bru

@@ -0,0 +1,8 @@
+meta {
+  name: Account
+  seq: 2
+}
+
+auth {
+  mode: inherit
+}

+ 7 - 4
src/auth.rs

@@ -1,5 +1,5 @@
 use mongodb::Database;
-use actix_web::{HttpRequest, cookie::Cookie};
+use actix_web::{HttpRequest};
 
 use crate::models::user::User;
 use crate::app_error::AppError;
@@ -7,8 +7,11 @@ use crate::app_error::AppError;
 pub async fn user_auth(
     db: &Database,
     req: &HttpRequest
-) -> Result<Cookie, AppError> {
-    let user_id = req.cookie("user")?.into_owned().value();
+) -> Result<User, AppError> {
+    let user_id = req.cookie("user")
+        .ok_or(AppError::Auth)?
+        .value()
+        .to_string();
     let user_collection = db.collection::<User>("users");
-    User::find_by_id(&user_collection, user_id).await?
+    Ok(User::find_by_id(&user_collection, user_id).await?)
 }

+ 21 - 4
src/controllers/account.rs

@@ -1,18 +1,35 @@
 use actix_web::{post, web, HttpResponse, HttpRequest};
 use mongodb::Database;
 
-use crate::models::account::{Account};
+use crate::models::{account::Account, user::User};
 use crate::auth::user_auth;
 use crate::app_error::AppError;
-use crate::dto::account;
+use crate::dto;
 
 #[post("/api/account")]
 pub async fn create_route(
     db: web::Data<Database>,
     req: HttpRequest,
-    body: web::Json<account::CreateInput>
+    body: web::Json<dto::account::CreateInput>
 ) -> Result<HttpResponse, AppError> {
     let user = user_auth(&db, &req).await?;
     let account_collection = db.collection::<Account>("accounts");
-    Ok(HttpResponse::Ok().body("Ok"))
+    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()
+    }
 }

+ 7 - 2
src/dto/account.rs

@@ -1,7 +1,12 @@
-use serde::Deserialize;
+use serde::{Serialize, Deserialize};
 
 #[derive(Deserialize)]
 pub struct CreateInput {
-    pub user: String,
+    pub data: String
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct ResponseAccount {
     pub data: String,
+    pub created_at: i64
 }

+ 40 - 2
src/models/account.rs

@@ -1,5 +1,10 @@
 use serde::{Serialize, Deserialize};
-use bson::{oid::ObjectId, DateTime};
+use bson::{oid::ObjectId, DateTime, Bson, doc};
+use mongodb::Collection;
+
+use crate::app_error::AppError;
+use crate::dto::account::CreateInput;
+use crate::models::user::User;
 
 #[derive(Serialize, Deserialize)]
 pub struct Account {
@@ -7,5 +12,38 @@ pub struct Account {
     pub _id: Option<ObjectId>,
     pub user: ObjectId,
     pub data: String,
-    pub created_date: DateTime
+    pub created_at: DateTime
+}
+
+impl Account {
+    pub async fn insert(collection: &Collection<Account>, input: CreateInput, user: User) -> Result<ObjectId, AppError> {
+        let object_id = match user._id {
+            Some(oid) => Ok(oid),
+            None => Err(AppError::Auth)
+        };
+
+        let account = Account {
+            _id: None,
+            user: object_id?,
+            data: input.data,
+            created_at: DateTime::now()
+        };
+
+        let result = collection
+            .insert_one(account, None)
+            .await?;
+
+        match result.inserted_id {
+            Bson::ObjectId(oid) => Ok(oid),
+            _ => Err(AppError::InternalError("Invalid Data".to_string()))
+        }
+    }
+
+    pub async fn find_by_id(collection: &Collection<Account>, account_id: ObjectId) -> Result<Account, AppError> {
+        match collection.find_one(doc!{"_id": account_id}, None).await {
+            Ok(Some(a)) => Ok(a),
+            Ok(None) => Err(AppError::invalid_input("No account with that ID")),
+            Err(e) => Err(AppError::Database(e.into()))
+        }
+    }
 }

+ 4 - 3
src/models/user.rs

@@ -43,10 +43,11 @@ impl User {
     }
 
     pub async fn find_by_id(collection: &Collection<User>, user_id: String) -> Result<User, AppError> {
-        let object_id = ObjectId::parse_str(id_str)?;
-        match collection.find_one(doc!{"_id", object_id}) {
+        let object_id = ObjectId::parse_str(user_id)
+            .map_err(|_| AppError::invalid_input("Invalid user ID"))?;
+        match collection.find_one(doc!{"_id": object_id}, None).await {
             Ok(Some(u)) => Ok(u),
-            Ok(None) => Err(AppError::auth),
+            Ok(None) => Err(AppError::Auth),
             Err(e) => Err(AppError::Database(e.into()))
         }
     }

+ 2 - 2
src/routes/account.rs

@@ -1,7 +1,7 @@
 use actix_web::web;
-use crate::controllers::user::{
+use crate::controllers::account::{
     create_route
-}
+};
 
 pub fn config(cfg: &mut web::ServiceConfig) {
     cfg.service(create_route);