DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

b487c450a27c0e35fc05ecc7e2736b77527b8c5e — Jonni Liljamo 1 year, 8 months ago 388ed83
feat(api, shared): patch game endpoint and request, cleanup unused apis
9 files changed, 70 insertions(+), 98 deletions(-)

D api/src/actions/game/info.rs
D api/src/actions/game/join.rs
M api/src/actions/game/mod.rs
A api/src/actions/game/patch.rs
M api/src/handlers/game/mod.rs
M api/src/main.rs
M shared/src/api/game/mod.rs
R shared/src/api/game/{patchstate.rs => patch.rs}
M shared/src/types/game.rs
D api/src/actions/game/info.rs => api/src/actions/game/info.rs +0 -14
@@ 1,14 0,0 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use diesel::PgConnection;
use laurelin_shared::error::api::APIError;

pub(crate) fn info(_conn: &mut PgConnection) -> Result<(), APIError> {
    Err(APIError::Undefined)
}

D api/src/actions/game/join.rs => api/src/actions/game/join.rs +0 -14
@@ 1,14 0,0 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use diesel::PgConnection;
use laurelin_shared::error::api::APIError;

pub(crate) fn join(_conn: &mut PgConnection) -> Result<(), APIError> {
    Err(APIError::Undefined)
}

M api/src/actions/game/mod.rs => api/src/actions/game/mod.rs +2 -5
@@ 15,8 15,5 @@ pub(crate) use all_forming::all_forming;
mod my_games;
pub(crate) use my_games::my_games;

mod info;
pub(crate) use info::info;

mod join;
pub(crate) use join::join;
mod patch;
pub(crate) use patch::patch;

A api/src/actions/game/patch.rs => api/src/actions/game/patch.rs +26 -0
@@ 0,0 1,26 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use diesel::{ExpressionMethods, PgConnection, RunQueryDsl};
use laurelin_schema::schema::games;
use laurelin_shared::{error::api::APIError, types::game::PatchGame};
use uuid::Uuid;

pub(crate) fn patch(
    conn: &mut PgConnection,
    game_id: &str,
    patch: &PatchGame,
) -> Result<(), APIError> {
    // TODO: handle stuffs, yeah?
    let _update_res = diesel::update(games::table)
        .filter(games::id.eq(Uuid::try_parse(game_id).unwrap()))
        .set(patch)
        .execute(conn);

    Ok(())
}

M api/src/handlers/game/mod.rs => api/src/handlers/game/mod.rs +22 -36
@@ 7,8 7,8 @@
 */

use actix_session::Session;
use actix_web::{get, post, web, HttpResponse, Responder};
use laurelin_shared::error::api::APIError;
use actix_web::{get, patch, post, web, HttpResponse, Responder};
use laurelin_shared::{error::api::APIError, types::game::PatchGame};

use crate::{actions, session, PgPool};



@@ 38,40 38,6 @@ async fn create(session: Session, pool: web::Data<PgPool>) -> impl Responder {
    }
}

#[get("/api/game/{id}")]
async fn info(
    session: Session,
    _pool: web::Data<PgPool>,
    _id: web::Path<String>,
) -> impl Responder {
    let session_validation = session::validate_session(&session);

    match session_validation {
        Err(err) => err,
        Ok(_user_id) => {
            //
            HttpResponse::Ok().body("INFO")
        }
    }
}

#[post("/api/game/{id}/join")]
async fn join(
    session: Session,
    _pool: web::Data<PgPool>,
    _id: web::Path<String>,
) -> impl Responder {
    let session_validation = session::validate_session(&session);

    match session_validation {
        Err(err) => err,
        Ok(_user_id) => {
            //
            HttpResponse::Ok().body("JOIN")
        }
    }
}

#[get("/api/game/all_forming")]
async fn all_forming(session: Session, pool: web::Data<PgPool>) -> impl Responder {
    let session_validation = session::validate_session(&session);


@@ 123,3 89,23 @@ async fn my_games(session: Session, pool: web::Data<PgPool>) -> impl Responder {
        }
    }
}

#[patch("/api/game/{id}")]
async fn patch(
    pool: web::Data<PgPool>,
    id: web::Path<String>,
    patch: web::Json<PatchGame>,
) -> impl Responder {
    let patch_res = web::block(move || {
        let mut conn = match pool.get() {
            Err(_) => return Err(APIError::DatabasePoolGetFailed),
            Ok(conn) => conn,
        };
        actions::game::patch(&mut conn, &id, &patch)
    })
    .await;
    match patch_res {
        Err(_err) => HttpResponse::InternalServerError().json(APIError::Undefined),
        Ok(_) => HttpResponse::Ok().into(),
    }
}

M api/src/main.rs => api/src/main.rs +1 -5
@@ 103,11 103,7 @@ async fn main() -> std::io::Result<()> {
            .service(handlers::game::create)
            .service(handlers::game::all_forming)
            .service(handlers::game::my_games)
            // NOTE: these have to be registered last!
            //       otherwise the positional {id} will catch
            //       things like "all_forming"
            .service(handlers::game::info)
            .service(handlers::game::join)
            .service(handlers::game::patch)
    })
    .bind(("0.0.0.0", 8080))?
    .run()

M shared/src/api/game/mod.rs => shared/src/api/game/mod.rs +2 -2
@@ 21,5 21,5 @@ pub use all_forming::*;
mod mygames;
pub use mygames::*;

//mod patchstate;
//pub use patchstate::*;
mod patch;
pub use patch::*;

R shared/src/api/game/patchstate.rs => shared/src/api/game/patch.rs +7 -21
@@ 9,35 9,21 @@
use reqwest;
use serde::{Deserialize, Serialize};

use super::{
    types::{Game, GameState},
    APIErrorWrapper,
};

#[derive(Serialize)]
pub struct PostState {
    pub state: GameState,
}
use crate::{error::api::APIError, types::game::PatchGame};

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ResponsePatchGameState {
    Error(APIErrorWrapper),
    Valid(Game),
pub enum ResponsePatchGame {
    Error(APIError),
    Valid(()),
}

pub fn patch_state(
    api_address: String,
    token: String,
    game_id: String,
    state: GameState,
) -> ResponsePatchGameState {
pub fn patch(api_address: String, game_id: String, patch: PatchGame) -> ResponsePatchGame {
    let client = reqwest::blocking::Client::new();

    let resp = client
        .patch(&format!("{}/game/{}/state", api_address, game_id))
        .header("Authorization", token)
        .json(&PostState { state })
        .patch(format!("{}/game/{}", api_address, game_id))
        .json(&patch)
        .send()
        .unwrap();


M shared/src/types/game.rs => shared/src/types/game.rs +10 -1
@@ 7,7 7,7 @@
 */

use chrono::NaiveDateTime;
use diesel::{Insertable, Queryable};
use diesel::{AsChangeset, Insertable, Queryable};
use naia_bevy_shared::Serde;
use serde::{Deserialize, Serialize};
use uuid::Uuid;


@@ 71,6 71,15 @@ pub struct InsertableGame {
    pub game_data_id: Uuid,
}

#[derive(Serialize, Deserialize, AsChangeset)]
#[diesel(table_name=games)]
pub struct PatchGame {
    pub guest_id: Option<Uuid>,
    pub state: Option<i16>,
    pub ended_at: Option<NaiveDateTime>,
    pub game_data_id: Option<Uuid>,
}

#[derive(Serialize, Deserialize, Queryable)]
pub struct Action {
    pub id: Uuid,