Browse Source

Create route to create a new character for the game

Lee Morgan 1 month ago
parent
commit
4439a32a08

+ 12 - 3
src/controllers/game/character/create.rs

@@ -1,9 +1,14 @@
 use actix_web::{HttpResponse, HttpRequest, web, post};
 use sqlx::PgPool;
 use serde::Deserialize;
+use uuid::Uuid;
 use crate::{
     http_error::HttpError,
-    auth::user_auth
+    auth::user_auth,
+    models::{
+        game::Game,
+        character::Character
+    }
 };
 
 #[derive(Deserialize)]
@@ -15,10 +20,14 @@ struct Body {
 #[post("/game/{game_id}/character")]
 pub async fn route(
     db: web::Data<PgPool>,
-    game_id: web::Path<String>,
+    path: web::Path<String>,
     web::Json(body): web::Json<Body>,
     req: HttpRequest
 ) -> Result<HttpResponse, HttpError> {
     let user = user_auth(&db, &req, true).await?;
-    Ok(HttpResponse::Ok().body("something"))
+    let game_id = Uuid::parse_str(&path.into_inner())?;
+    let game = Game::get_one(&db, game_id, Some(user.id)).await?;
+    let character = Character::new(game.id, body.name, body.description);
+    character.insert(&db).await?;
+    Ok(HttpResponse::Ok().json(character))
 }

+ 30 - 0
src/models/character.rs

@@ -1,8 +1,38 @@
 use uuid::Uuid;
+use sqlx::PgPool;
+use serde::Serialize;
+use crate::http_error::HttpError;
 
+#[derive(Serialize)]
 pub struct Character {
     pub id: Uuid,
     pub game_id: Uuid,
     pub name: String,
     pub description: String
 }
+
+impl Character {
+    pub fn new(game_id: Uuid, name: String, description: String) -> Self {
+        Self {
+            id: Uuid::now_v7(),
+            game_id: game_id,
+            name: name,
+            description: description
+        }
+    }
+
+    pub async fn insert(&self, db: &PgPool) -> Result<(), HttpError> {
+        sqlx::query(
+            "INSERT INTO characters(id, game_id, name, description)
+            VALUES($1, $2, $3, $4)"
+        ) 
+            .bind(&self.id)
+            .bind(&self.game_id)
+            .bind(&self.name)
+            .bind(&self.description)
+            .execute(db)
+            .await?;
+
+        Ok(())
+    }
+}

+ 21 - 3
src/models/game.rs

@@ -1,10 +1,10 @@
 use uuid::Uuid;
 use chrono::{DateTime, Utc};
-use sqlx::PgPool;
+use sqlx::{PgPool, FromRow};
 use serde::Serialize;
 use crate::http_error::HttpError;
 
-#[derive(Serialize)]
+#[derive(Serialize, FromRow)]
 pub struct Game {
     pub id: Uuid,
     pub user_id: Uuid,
@@ -26,7 +26,7 @@ impl Game {
 
     pub async fn insert(&self, db: &PgPool) -> Result<(), HttpError> {
         sqlx::query(
-            "INSERT into games(id, user_id, title, game_context, created_at)
+            "INSERT INTO games(id, user_id, title, game_context, created_at)
             VALUES($1, $2, $3, $4, $5)"
         )
             .bind(&self.id)
@@ -39,4 +39,22 @@ impl Game {
 
         Ok(())
     }
+
+    pub async fn get_one(db: &PgPool, id: Uuid, user_id: Option<Uuid>) -> Result<Game, HttpError> {
+        let result = sqlx::query_as::<_, Game>(
+            "SELECT *
+            FROM games
+            WHERE id = $1
+                AND ($2::uuid IS NULL OR user_id = $2)"
+        )
+            .bind(id)
+            .bind(user_id)
+            .fetch_optional(db)
+            .await?;
+
+        match result {
+            Some(g) => Ok(g),
+            None => Err(HttpError::NotFound("Game not found".into()))
+        }
+    }
 }

+ 1 - 1
src/routes/game/character.rs

@@ -1,5 +1,5 @@
 use actix_web::web::ServiceConfig;
-use crate::controllers::game::{
+use crate::controllers::game::character::{
     create
 };