Prechádzať zdrojové kódy

Create route for device creation

Lee Morgan 2 mesiacov pred
rodič
commit
268f3cac2a

+ 0 - 1
docs/paths/device/create.yaml

@@ -20,7 +20,6 @@ requestBody:
         type: object
         required:
           - name
-          - description
         properties:
           name:
             type: string

+ 30 - 0
src/controllers/device/create.rs

@@ -0,0 +1,30 @@
+use actix_web::{HttpResponse, HttpRequest, web, post};
+use serde::Deserialize;
+use sqlx::PgPool;
+use uuid::Uuid;
+use crate::{
+    app_error::AppError,
+    auth::user_auth,
+    models::device::Device
+};
+
+#[derive(Deserialize)]
+struct Body{
+    name: String,
+    description: Option<String>
+}
+
+#[post("/home/{home_id}/device")]
+pub async fn route(
+    db: web::Data<PgPool>,
+    path: web::Path<String>,
+    body: web::Json<Body>,
+    req: HttpRequest
+) -> Result<HttpResponse, AppError> {
+    let user = user_auth(&db, &req).await?;
+    let home_id = Uuid::parse_str(&path.into_inner())?;
+    let body = body.into_inner();
+    let device = Device::new(home_id, body.name, body.description);
+    device.insert(&db, user.id, home_id).await?;
+    Ok(HttpResponse::Ok().json(device))
+}

+ 1 - 0
src/controllers/device/mod.rs

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

+ 1 - 0
src/controllers/mod.rs

@@ -1,2 +1,3 @@
 pub mod user;
 pub mod home;
+pub mod device;

+ 1 - 0
src/main.rs

@@ -41,6 +41,7 @@ async fn main() -> Result<(), AppError> {
             )
             .configure(routes::user::config)
             .configure(routes::home::config)
+            .configure(routes::device::config)
     })
         .bind(("0.0.0.0", 8000))
         .expect("Failed to bind to port")

+ 48 - 1
src/models/device.rs

@@ -1,8 +1,55 @@
 use uuid::Uuid;
+use serde::Serialize;
+use sqlx::{PgPool, postgres::PgQueryResult};
+use crate::app_error::AppError;
 
+#[derive(Serialize)]
 pub struct Device {
     id: Uuid,
     home_id: Uuid,
     name: String,
-    description: String
+    description: Option<String>
+}
+
+impl Device {
+    pub fn new(home_id: Uuid, name: String, description: Option<String>) -> Self {
+        Self {
+            id: Uuid::now_v7(),
+            home_id: home_id,
+            name: name,
+            description: description
+        }
+    }
+
+    pub async fn insert(
+        &self,
+        db: &PgPool,
+        user_id: Uuid,
+        home_id: Uuid
+    ) -> Result<(), AppError> {
+        let result: PgQueryResult = sqlx::query!(
+            "INSERT INTO devices (id, home_id, name, description)
+            SELECT $1, $2, $3, $4
+            WHERE EXISTS (
+                SELECT 1
+                FROM users_homes
+                WHERE user_id = $5
+                    AND home_id = $2
+                    AND is_admin = true
+            )",
+            self.id,
+            home_id,
+            self.name,
+            self.description,
+            user_id
+        )
+            .execute(db)
+            .await?;
+
+        if result.rows_affected() == 0 {
+            return Err(AppError::forbidden("Unauthorized access to home"));
+        }
+
+        Ok(())
+    }
 }

+ 8 - 0
src/routes/device.rs

@@ -0,0 +1,8 @@
+use actix_web::web;
+use crate::controllers::device::{
+    create
+};
+
+pub fn config(cfg: &mut web::ServiceConfig) {
+    cfg.service(create::route);
+}

+ 1 - 0
src/routes/mod.rs

@@ -1,2 +1,3 @@
 pub mod user;
 pub mod home;
+pub mod device;