diff --git a/lootalot_db/src/lib.rs b/lootalot_db/src/lib.rs index 8c76b1c..a209239 100644 --- a/lootalot_db/src/lib.rs +++ b/lootalot_db/src/lib.rs @@ -120,13 +120,10 @@ impl<'q> AsPlayer<'q> { Ok(models::Item::owned_by(self.id).load(self.conn)?) } /// Buy an item and add it to this player chest - /// /// TODO: Items should be picked from a custom list /// - /// # Panics - /// - /// This currently panics if player wealth fails to be updated, as this is - /// a serious error. + /// # Returns + /// Result containing the difference in coins after operation pub fn buy<'a>(self, name: &'a str, price: i32) -> ActionResult<(i32, i32, i32, i32)> { self.conn.transaction(|| { let new_item = models::item::NewLoot::to_player(self.id, (name, price)); @@ -139,14 +136,11 @@ impl<'q> AsPlayer<'q> { })?; self.update_wealth(-(price as f32)) }) - } /// Sell an item from this player chest /// - /// # Panics - /// - /// This currently panics if player wealth fails to be updated, as this is - /// a serious error. + /// # Returns + /// Result containing the difference in coins after operation pub fn sell( self, loot_id: i32, diff --git a/lootalot_front/src/AppStorage.js b/lootalot_front/src/AppStorage.js index 28c3c6e..da5a0e0 100644 --- a/lootalot_front/src/AppStorage.js +++ b/lootalot_front/src/AppStorage.js @@ -18,13 +18,29 @@ export const Api = { return fetch(API_ENDPOINT(playerId + "/loot")) .then(r => r.json()) }, - putClaim (playerId, itemId) { - return fetch(API_ENDPOINT(playerId + "/claim/" + itemId)) - .then(r => r.json()) + putClaim (player_id, item_id) { + const payload = { player_id, item_id }; + return fetch(API_ENDPOINT("claims"), + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload) + }) + .then(r => r.json()) }, - unClaim (playerId, itemId) { - return fetch(API_ENDPOINT(playerId + "/unclaim/" + itemId)) - .then(r => r.json()) + unClaim (player_id, item_id) { + const payload = { player_id, item_id }; + return fetch(API_ENDPOINT("claims"), + { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload) + }) + .then(r => r.json()) }, updateWealth (playerId, goldValue) { return fetch(API_ENDPOINT(playerId + "/update-wealth/" + goldValue)) @@ -83,7 +99,7 @@ export const AppStorage = { // Sets a new active player by id setActivePlayer (newPlayerId) { if (this.debug) console.log('setActivePlayer to ', newPlayerId) - this.state.player_id = newPlayerId + this.state.player_id = Number(newPlayerId) document.cookie = `player_id=${newPlayerId};`; }, // Show/Hide player's chest diff --git a/src/main.rs b/src/main.rs index 728aaa6..089780e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate actix_web; extern crate dotenv; extern crate env_logger; extern crate lootalot_db; +extern crate serde; mod server; diff --git a/src/server.rs b/src/server.rs index 46cd67e..9ae5f41 100644 --- a/src/server.rs +++ b/src/server.rs @@ -4,7 +4,7 @@ use actix_web::{web, App, Error, HttpResponse, HttpServer}; use futures::Future; use lootalot_db::{DbApi, Pool, QueryResult}; use std::env; - +use serde::{Serialize, Deserialize}; type AppPool = web::Data; /// Wraps call to the DbApi and process its result as a async HttpResponse @@ -49,6 +49,12 @@ pub fn db_call< }) } +#[derive(Serialize, Deserialize, Debug)] +struct PlayerClaim { + player_id: i32, + item_id: i32, +} + pub(crate) fn serve() -> std::io::Result<()> { let www_root: String = env::var("WWW_ROOT").expect("WWW_ROOT must be set"); dbg!(&www_root); @@ -60,7 +66,7 @@ pub(crate) fn serve() -> std::io::Result<()> { .wrap( Cors::new() .allowed_origin("http://localhost:8080") - .allowed_methods(vec!["GET", "POST"]) + .allowed_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"]) .max_age(3600), ) .service( @@ -71,11 +77,25 @@ pub(crate) fn serve() -> std::io::Result<()> { db_call(pool, move |api| api.fetch_players()) }), ) - .route( - "/claims", - web::get().to_async(move |pool: AppPool| { - db_call(pool, move |api| api.fetch_claims()) - }), + .service( + web::resource("/claims") + .route(web::get() + .to_async(move |pool: AppPool| { + db_call(pool, move |api| api + .fetch_claims()) + })) + .route(web::put() + .to_async(move |pool: AppPool, data: web::Json| { + db_call(pool, move |api| api + .as_player(data.player_id) + .claim(data.item_id)) + })) + .route(web::delete() + .to_async(move |pool: AppPool, data: web::Json| { + db_call(pool, move |api| api + .as_player(data.player_id) + .unclaim(data.item_id)) + })) ) .route( "/{player_id}/update-wealth/{amount}", @@ -89,34 +109,24 @@ pub(crate) fn serve() -> std::io::Result<()> { db_call(pool, move |api| api.as_player(*player_id).loot()) }), ) - .route( - "/{player_id}/claim/{item_id}", - web::get().to_async(move |pool: AppPool, data: web::Path<(i32, i32)>| { - db_call(pool, move |api| api.as_player(data.0).claim(data.1)) - }), + .service(web::scope("/admin") + .route( + "/resolve-claims", + web::get().to_async(move |pool: AppPool| { + db_call(pool, move |api| api.as_admin().resolve_claims()) + }), + ) + .route( + "/add-player/{name}/{wealth}", + web::get().to_async( + move |pool: AppPool, data: web::Path<(String, f32)>| { + db_call(pool, move |api| { + api.as_admin().add_player(&data.0, data.1) + }) + }, + ), + ) ) - .route( - "/{player_id}/unclaim/{item_id}", - web::get().to_async(move |pool: AppPool, data: web::Path<(i32, i32)>| { - db_call(pool, move |api| api.as_player(data.0).unclaim(data.1)) - }), - ) - .route( - "/admin/resolve-claims", - web::get().to_async(move |pool: AppPool| { - db_call(pool, move |api| api.as_admin().resolve_claims()) - }), - ) - .route( - "/admin/add-player/{name}/{wealth}", - web::get().to_async( - move |pool: AppPool, data: web::Path<(String, f32)>| { - db_call(pool, move |api| { - api.as_admin().add_player(&data.0, data.1) - }) - }, - ), - ), ) .service(fs::Files::new("/", www_root.clone()).index_file("index.html")) })