diff --git a/backend-actix/Cargo.lock b/backend-actix/Cargo.lock index 6b54188..bb961e2 100644 --- a/backend-actix/Cargo.lock +++ b/backend-actix/Cargo.lock @@ -338,9 +338,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82" [[package]] name = "bitflags" @@ -416,9 +416,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.50" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "jobserver", @@ -516,9 +516,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -872,6 +872,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "ff" version = "0.13.1" @@ -890,9 +900,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] name = "flate2" @@ -972,9 +982,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1249,15 +1259,15 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8" dependencies = [ "jiff-static", "log", @@ -1268,9 +1278,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" dependencies = [ "proc-macro2", "quote", @@ -1337,9 +1347,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.178" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libm" @@ -1664,9 +1674,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "portable-atomic-util" @@ -1745,9 +1755,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -1928,9 +1938,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "scheduled-thread-pool" @@ -1999,15 +2009,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.146" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -2061,10 +2071,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -2164,9 +2175,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.111" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -2247,9 +2258,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -2263,9 +2274,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -2848,6 +2859,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zmij" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e0d8dffbae3d840f64bda38e28391faef673a7b5a6017840f2a106c8145868" + [[package]] name = "zstd" version = "0.13.3" diff --git a/backend-actix/gamenight-api.yaml b/backend-actix/gamenight-api.yaml index b7ccc00..d150a01 100644 --- a/backend-actix/gamenight-api.yaml +++ b/backend-actix/gamenight-api.yaml @@ -201,9 +201,21 @@ paths: $ref: '#/components/requestBodies/AddGameRequest' security: - JWT-Auth: [] + delete: + responses: + '200': + description: "Ok" + '401': + $ref: '#/components/responses/FailureResponse' + '422': + $ref: '#/components/responses/FailureResponse' + requestBody: + $ref: '#/components/requestBodies/RemoveGameRequest' + security: + - JWT-Auth: [ ] /rename_game: post: - responses: + responses: '200': description: "OK" '401': @@ -315,9 +327,6 @@ paths: $ref: '#/components/requestBodies/AuthorizedLocationUserIdsRequest' security: - JWT-Auth: [] - - - components: schemas: Gamenight: @@ -590,6 +599,11 @@ components: application/json: schema: $ref: '#/components/schemas/RenameGameRequestBody' + RemoveGameRequest: + content: + application/json: + schema: + $ref: '#/components/schemas/GameId' OwnGameRequest: content: application/json: diff --git a/backend-actix/src/main.rs b/backend-actix/src/main.rs index 96ef763..4da5319 100644 --- a/backend-actix/src/main.rs +++ b/backend-actix/src/main.rs @@ -21,7 +21,7 @@ async fn main() -> std::io::Result<()> { let mut conn = pool.get_conn(); run_migration(&mut conn); - env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug")); HttpServer::new(move || { let cors = Cors::default() @@ -56,6 +56,7 @@ async fn main() -> std::io::Result<()> { .service(post_own_game) .service(post_disown_game) .service(get_owned_games) + .service(delete_game) .service(get_locations) .service(post_location) .service(post_location_authorize) diff --git a/backend-actix/src/request/authorization.rs b/backend-actix/src/request/authorization.rs index bea9f0a..1c2cf25 100644 --- a/backend-actix/src/request/authorization.rs +++ b/backend-actix/src/request/authorization.rs @@ -21,13 +21,6 @@ pub struct Claims { pub struct AuthUser(pub User); -// pub struct AuthUser { -// pub id: Uuid, -// pub username: String, -// pub email: String, -// pub role: Role, -// } - impl From for AuthUser { fn from(value: User) -> Self { Self(value) diff --git a/backend-actix/src/request/game.rs b/backend-actix/src/request/game.rs index b42f357..4628b38 100644 --- a/backend-actix/src/request/game.rs +++ b/backend-actix/src/request/game.rs @@ -1,10 +1,17 @@ -use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder}; +use crate::game::rename_game; +use crate::owned_game::own_game; +use crate::owned_game::owned_games; +use crate::owned_game::disown_game; +use crate::owned_game::OwnedGame; +use gamenight_database::game::load_game; +use crate::game::insert_game; +use uuid::Uuid; +use crate::game::remove_game; +use actix_web::{delete, get, http::header::ContentType, post, web, HttpResponse, Responder}; use gamenight_database::{ - game::{insert_game, load_game, rename_game}, - owned_game::{disown_game, own_game, owned_games, OwnedGame}, + user::Role, DbPool, GetConnection, }; -use uuid::Uuid; use crate::{ models::{ @@ -77,6 +84,22 @@ pub async fn post_game( .body(serde_json::to_string(&GameId{game_id: game.id.to_string()})?)) } +#[delete("/game")] +pub async fn delete_game( + pool: web::Data, + user: AuthUser, + game_id: web::Json, +) -> Result { + if user.0.role != Role::Admin { + Ok(HttpResponse::Unauthorized()) + } else { + let mut conn = pool.get_conn(); + remove_game(&mut conn, Uuid::parse_str(&game_id.0.game_id)?)?; + + Ok(HttpResponse::Ok()) + } +} + #[post("/rename_game")] pub async fn post_rename_game( pool: web::Data, diff --git a/backend-actix/src/request/mod.rs b/backend-actix/src/request/mod.rs index e2f40e9..6ae8db0 100644 --- a/backend-actix/src/request/mod.rs +++ b/backend-actix/src/request/mod.rs @@ -15,6 +15,7 @@ pub use game::post_disown_game; pub use game::post_game; pub use game::post_own_game; pub use game::post_rename_game; +pub use game::delete_game; pub use gamenight_handlers::gamenight_get; pub use gamenight_handlers::gamenight_post; pub use gamenight_handlers::gamenights; diff --git a/gamenight-api-client-rs/README.md b/gamenight-api-client-rs/README.md index 355f48b..e4f17de 100644 --- a/gamenight-api-client-rs/README.md +++ b/gamenight-api-client-rs/README.md @@ -29,6 +29,7 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *DefaultApi* | [**authorized_location_user_ids_get**](docs/DefaultApi.md#authorized_location_user_ids_get) | **GET** /authorized_location_user_ids | *DefaultApi* | [**disown_post**](docs/DefaultApi.md#disown_post) | **POST** /disown | +*DefaultApi* | [**game_delete**](docs/DefaultApi.md#game_delete) | **DELETE** /game | *DefaultApi* | [**game_get**](docs/DefaultApi.md#game_get) | **GET** /game | *DefaultApi* | [**game_post**](docs/DefaultApi.md#game_post) | **POST** /game | *DefaultApi* | [**games_get**](docs/DefaultApi.md#games_get) | **GET** /games | diff --git a/gamenight-api-client-rs/docs/DefaultApi.md b/gamenight-api-client-rs/docs/DefaultApi.md index 8912504..703f377 100644 --- a/gamenight-api-client-rs/docs/DefaultApi.md +++ b/gamenight-api-client-rs/docs/DefaultApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**authorized_location_user_ids_get**](DefaultApi.md#authorized_location_user_ids_get) | **GET** /authorized_location_user_ids | [**disown_post**](DefaultApi.md#disown_post) | **POST** /disown | +[**game_delete**](DefaultApi.md#game_delete) | **DELETE** /game | [**game_get**](DefaultApi.md#game_get) | **GET** /game | [**game_post**](DefaultApi.md#game_post) | **POST** /game | [**games_get**](DefaultApi.md#games_get) | **GET** /games | @@ -86,6 +87,34 @@ Name | Type | Description | Required | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## game_delete + +> game_delete(game_id) + + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**game_id** | Option<[**GameId**](GameId.md)> | | | + +### Return type + + (empty response body) + +### Authorization + +[JWT-Auth](../README.md#JWT-Auth) + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## game_get > models::Game game_get(game_id) diff --git a/gamenight-api-client-rs/src/apis/default_api.rs b/gamenight-api-client-rs/src/apis/default_api.rs index 4d33346..7cf1253 100644 --- a/gamenight-api-client-rs/src/apis/default_api.rs +++ b/gamenight-api-client-rs/src/apis/default_api.rs @@ -33,6 +33,15 @@ pub enum DisownPostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`game_delete`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GameDeleteError { + Status401(models::Failure), + Status422(models::Failure), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`game_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -290,6 +299,35 @@ pub async fn disown_post(configuration: &configuration::Configuration, game_id: } } +pub async fn game_delete(configuration: &configuration::Configuration, game_id: Option) -> Result<(), Error> { + // add a prefix to parameters to efficiently prevent name collisions + let p_body_game_id = game_id; + + let uri_str = format!("{}/game", configuration.base_path); + let mut req_builder = configuration.client.request(reqwest::Method::DELETE, &uri_str); + + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + req_builder = req_builder.json(&p_body_game_id); + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + if !status.is_client_error() && !status.is_server_error() { + Ok(()) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { status, content, entity })) + } +} + pub async fn game_get(configuration: &configuration::Configuration, game_id: Option) -> Result> { // add a prefix to parameters to efficiently prevent name collisions let p_body_game_id = game_id; diff --git a/gamenight-cli/Cargo.lock b/gamenight-cli/Cargo.lock index b3dfe36..7bc5892 100644 --- a/gamenight-cli/Cargo.lock +++ b/gamenight-cli/Cargo.lock @@ -72,9 +72,9 @@ checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.50" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "shlex", @@ -193,9 +193,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] name = "foreign-types" @@ -635,9 +635,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -645,9 +645,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" @@ -676,9 +676,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.178" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "linux-raw-sys" @@ -936,9 +936,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -969,9 +969,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -1021,9 +1021,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", @@ -1049,9 +1049,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "schannel" @@ -1123,15 +1123,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.146" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -1186,10 +1186,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -1235,9 +1236,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "syn" -version = "2.0.111" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -1266,9 +1267,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", @@ -1349,9 +1350,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -2010,3 +2011,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e0d8dffbae3d840f64bda38e28391faef673a7b5a6017840f2a106c8145868" diff --git a/gamenight-cli/src/domain/gamenight.rs b/gamenight-cli/src/domain/gamenight.rs index 29b0030..88a7d52 100644 --- a/gamenight-cli/src/domain/gamenight.rs +++ b/gamenight-cli/src/domain/gamenight.rs @@ -1,19 +1,27 @@ -use std::fmt::Display; - +use std::fmt::{Display, Formatter}; use chrono::{DateTime, Local}; use uuid::Uuid; +use crate::domain::owned_games::OwnedGames; +use crate::domain::participants::Participants; +use crate::domain::user::User; #[derive(Clone)] pub struct Gamenight { pub id: Uuid, pub name: String, pub start_time: DateTime, - pub owner_id: Uuid, + pub organizer: User, + pub participants: Participants, + pub owned_games: OwnedGames, } impl Display for Gamenight { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, r#"Name: {} -When: {}"#, self.name, self.start_time.format("%d-%m-%Y %H:%M")) + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Name: {}", self.name)?; + writeln!(f, "Organizer: {}", self.organizer)?; + writeln!(f, "Start: {}", self.start_time.to_rfc3339())?; + writeln!(f, "Participants: {}", self.participants)?; + write!(f, "Owned games:\n{}", self.owned_games)?; + Ok(()) } } \ No newline at end of file diff --git a/gamenight-cli/src/domain/gamenight_select_data.rs b/gamenight-cli/src/domain/gamenight_select_data.rs new file mode 100644 index 0000000..04bf39b --- /dev/null +++ b/gamenight-cli/src/domain/gamenight_select_data.rs @@ -0,0 +1,19 @@ +use std::fmt::Display; + +use chrono::{DateTime, Local}; +use uuid::Uuid; + +#[derive(Clone)] +pub struct GamenightSelectData { + pub id: Uuid, + pub name: String, + pub start_time: DateTime, + pub owner_id: Uuid, +} + +impl Display for GamenightSelectData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, r#"Name: {} +When: {}"#, self.name, self.start_time.format("%d-%m-%Y %H:%M")) + } +} \ No newline at end of file diff --git a/gamenight-cli/src/flows/flow_helpers.rs b/gamenight-cli/src/domain/location_select_data.rs similarity index 100% rename from gamenight-cli/src/flows/flow_helpers.rs rename to gamenight-cli/src/domain/location_select_data.rs diff --git a/gamenight-cli/src/domain/mod.rs b/gamenight-cli/src/domain/mod.rs index af54e9e..5642de2 100644 --- a/gamenight-cli/src/domain/mod.rs +++ b/gamenight-cli/src/domain/mod.rs @@ -1,7 +1,9 @@ -pub mod gamenight; +pub mod gamenight_select_data; pub mod user; pub mod config; pub mod participants; pub mod game; pub mod owned_games; -pub mod location; \ No newline at end of file +pub mod location; +pub mod location_select_data; +pub mod gamenight; \ No newline at end of file diff --git a/gamenight-cli/src/domain/owned_games.rs b/gamenight-cli/src/domain/owned_games.rs index dffc991..834ebe4 100644 --- a/gamenight-cli/src/domain/owned_games.rs +++ b/gamenight-cli/src/domain/owned_games.rs @@ -2,12 +2,12 @@ use std::{collections::HashMap, fmt::Display}; use crate::domain::game::Game; +#[derive(Clone)] +pub struct OwnedGames(pub HashMap>); -pub struct OwnedGames<'a>(pub &'a HashMap>); - -impl<'a> Display for OwnedGames<'a> { +impl Display for OwnedGames { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for (k,v) in self.0 { + for (k,v) in &self.0 { write!(f, "{k}:\n")?; for g in v { write!(f, "\t{}\n", g.name)?; diff --git a/gamenight-cli/src/domain/participants.rs b/gamenight-cli/src/domain/participants.rs index df5ddab..7b85244 100644 --- a/gamenight-cli/src/domain/participants.rs +++ b/gamenight-cli/src/domain/participants.rs @@ -2,9 +2,10 @@ use std::fmt::Display; use crate::domain::user::User; -pub struct Participants<'a>(pub &'a Vec); +#[derive(Clone)] +pub struct Participants(pub Vec); -impl<'a> Display for Participants<'a> { +impl<'a> Display for Participants { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let string_list: Vec = self.0.iter().map(|x| {format!("{x}")}).collect(); write!(f, "{}", string_list.join(", ")) diff --git a/gamenight-cli/src/domain/user.rs b/gamenight-cli/src/domain/user.rs index bc051f4..96f1126 100644 --- a/gamenight-cli/src/domain/user.rs +++ b/gamenight-cli/src/domain/user.rs @@ -1,6 +1,7 @@ use std::fmt::Display; - +use gamenight_api_client_rs::models; use uuid::Uuid; +use crate::flows::FlowError; #[derive(Clone)] pub struct User { @@ -13,4 +14,15 @@ impl Display for User { write!(f, "{}", self.username) } +} + +impl TryFrom for User { + type Error = FlowError; + + fn try_from(user: models::User) -> Result { + Ok(Self { + username: user.username, + id: Uuid::parse_str(&user.id)? + }) + } } \ No newline at end of file diff --git a/gamenight-cli/src/flows/add_game.rs b/gamenight-cli/src/flows/add_game.rs index 6444962..4e671a9 100644 --- a/gamenight-cli/src/flows/add_game.rs +++ b/gamenight-cli/src/flows/add_game.rs @@ -1,12 +1,10 @@ use std::fmt::Display; -use async_trait::async_trait; -use gamenight_api_client_rs::{apis::default_api::game_post, models::AddGameRequestBody, models::OwnGameRequestBody}; -use gamenight_api_client_rs::apis::default_api::{locations_get, own_post}; -use inquire::{Confirm, Select, Text}; -use crate::flows::flow_helpers::LocationSelectData; -use crate::flows::own::Own; use super::*; +use crate::flows::own::Own; +use async_trait::async_trait; +use gamenight_api_client_rs::{apis::default_api::game_post, models::AddGameRequestBody}; +use inquire::Text; #[derive(Clone)] diff --git a/gamenight-cli/src/flows/list_gamenights.rs b/gamenight-cli/src/flows/list_gamenights.rs index 2374ead..a4010f7 100644 --- a/gamenight-cli/src/flows/list_gamenights.rs +++ b/gamenight-cli/src/flows/list_gamenights.rs @@ -4,7 +4,7 @@ use gamenight_api_client_rs::apis::default_api::get_gamenights; use inquire::Select; use uuid::Uuid; -use crate::{domain::{gamenight::Gamenight}, flows::view_gamenight::ViewGamenight}; +use crate::{domain::{gamenight_select_data::GamenightSelectData}, flows::view_gamenight::ViewGamenight}; use super::{exit::Exit, *}; @@ -27,7 +27,7 @@ impl<'a> Flow<'a> for ListGamenights { let mut view_flows: Vec + Send>> = vec![]; for response in response.iter() { - let gamenight = Gamenight { + let gamenight = GamenightSelectData { id: Uuid::parse_str(&response.id)?, name: response.name.clone(), start_time:DateTime::parse_from_rfc3339(&response.datetime)?.into(), diff --git a/gamenight-cli/src/flows/locations.rs b/gamenight-cli/src/flows/locations.rs index e69577b..a25734d 100644 --- a/gamenight-cli/src/flows/locations.rs +++ b/gamenight-cli/src/flows/locations.rs @@ -7,7 +7,6 @@ use crate::flows::{add_location::AddLocation, exit::Exit, list_locations::ListLo use super::*; - #[derive(Clone)] pub struct Locations { } diff --git a/gamenight-cli/src/flows/mod.rs b/gamenight-cli/src/flows/mod.rs index 5e251fd..f03daf5 100644 --- a/gamenight-cli/src/flows/mod.rs +++ b/gamenight-cli/src/flows/mod.rs @@ -35,7 +35,7 @@ mod list_locations; mod view_location; mod add_location; mod location_authorize; -mod flow_helpers; +mod remove_game; pub struct GamenightState { api_configuration: Configuration, @@ -140,7 +140,7 @@ impl From for FlowError { pub enum FlowOutcome { Successful, Cancelled, - Abort + Abort, } type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>; diff --git a/gamenight-cli/src/flows/own.rs b/gamenight-cli/src/flows/own.rs index 362a132..b25db0b 100644 --- a/gamenight-cli/src/flows/own.rs +++ b/gamenight-cli/src/flows/own.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use super::{Flow, FlowError, FlowOutcome, FlowResult, GamenightState}; -use crate::flows::flow_helpers::LocationSelectData; +use crate::domain::location_select_data::LocationSelectData; use async_trait::async_trait; use gamenight_api_client_rs::apis::default_api::locations_get; use gamenight_api_client_rs::models::OwnGameRequestBody; diff --git a/gamenight-cli/src/flows/remove_game.rs b/gamenight-cli/src/flows/remove_game.rs new file mode 100644 index 0000000..63bd1a9 --- /dev/null +++ b/gamenight-cli/src/flows/remove_game.rs @@ -0,0 +1,38 @@ +use std::fmt::Display; + +use async_trait::async_trait; +use gamenight_api_client_rs::models::GameId; + +use super::{Flow, FlowOutcome, FlowResult, GamenightState}; +use crate::domain::game::Game; + +#[derive(Clone)] +pub struct RemoveGame { + pub game: Game +} + +impl RemoveGame { + pub fn new(game: Game) -> Self { + Self{ + game + } + } +} + +#[async_trait] +impl<'a> Flow<'a> for RemoveGame { + async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> { + let req = GameId { + game_id: self.game.id.to_string() + }; + gamenight_api_client_rs::apis::default_api::game_delete(&state.api_configuration, Some(req)).await?; + //Hack to return to right stack item, skipping detail view that doesn't exist. + Ok((FlowOutcome::Abort, state)) + } +} + +impl Display for RemoveGame { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Remove") + } +} \ No newline at end of file diff --git a/gamenight-cli/src/flows/view_game.rs b/gamenight-cli/src/flows/view_game.rs index d869bdf..cbdff29 100644 --- a/gamenight-cli/src/flows/view_game.rs +++ b/gamenight-cli/src/flows/view_game.rs @@ -4,7 +4,7 @@ use inquire::Select; use uuid::Uuid; use crate::{domain::game::Game, flows::{disown::Disown, exit::Exit, own::Own, rename_game::RenameGame}}; - +use crate::flows::remove_game::RemoveGame; use super::*; #[derive(Clone)] @@ -45,6 +45,7 @@ impl<'a> Flow<'a> for ViewGame { let options: Vec + Send>> = vec![ own_or_disown, + Box::new(RemoveGame::new(game.clone())), Box::new(RenameGame::new(game.clone())), Box::new(Exit::new()) ]; diff --git a/gamenight-cli/src/flows/view_gamenight.rs b/gamenight-cli/src/flows/view_gamenight.rs index 6052769..07e0d16 100644 --- a/gamenight-cli/src/flows/view_gamenight.rs +++ b/gamenight-cli/src/flows/view_gamenight.rs @@ -1,24 +1,23 @@ - +use crate::domain::gamenight::Gamenight; use std::collections::HashMap; use futures::future::join_all; use gamenight_api_client_rs::{apis::default_api::{game_get, owned_games_get, participants_get, user_get, GameGetError}, models::{self, GameId, GamenightId, UserId}}; use inquire::Select; -use uuid::Uuid; -use crate::{domain::{game::Game, gamenight::Gamenight, owned_games::OwnedGames, participants::Participants, user::User}, flows::{exit::Exit, join::Join, leave::Leave}}; +use crate::{domain::{game::Game, gamenight_select_data::GamenightSelectData, owned_games::OwnedGames, participants::Participants}, flows::{exit::Exit, join::Join, leave::Leave}}; use super::*; #[derive(Clone)] pub struct ViewGamenight { - gamenight: Gamenight + pub gamenight_select_data: GamenightSelectData, } impl ViewGamenight { - pub fn new(gamenight: Gamenight) -> Self { + pub fn new(gamenight_select_data: GamenightSelectData) -> Self { Self { - gamenight + gamenight_select_data } } } @@ -26,38 +25,41 @@ impl ViewGamenight { #[async_trait] impl<'a> Flow<'a> for ViewGamenight { async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> { - - let participants = participants_get(&state.api_configuration, Some(GamenightId{gamenight_id: self.gamenight.id.to_string()})).await?; - let mut users = vec![]; + let mut gamenight = Gamenight { + id: self.gamenight_select_data.id, + start_time: self.gamenight_select_data.start_time, + name: self.gamenight_select_data.name.clone(), + organizer: user_get(&state.api_configuration, Some(UserId{user_id: self.gamenight_select_data.owner_id.to_string()})).await?.try_into()?, + participants: Participants(vec![]), + owned_games: OwnedGames(HashMap::new()) + }; + + let participants = participants_get(&state.api_configuration, Some(GamenightId{gamenight_id: gamenight.id.to_string()})).await?; + for participant in participants.participants.iter() { - let user = user_get(&state.api_configuration, Some(UserId{user_id: participant.clone()})).await?; - users.push(User { - id: Uuid::parse_str(&user.id)?, - username: user.username - }); + gamenight.participants.0.push(user_get(&state.api_configuration, Some(UserId{user_id: participant.clone()})).await?.try_into()?); } - let mut user_games: HashMap> = HashMap::new(); - for user in &users { + for user in &gamenight.participants.0 { let request = UserId{ user_id: user.id.to_string() }; let games: Vec = join_all(owned_games_get(&state.api_configuration, Some(request)).await? .iter().map(async |game_id| -> Result> { let request = GameId{ game_id: game_id.clone() }; game_get(&state.api_configuration, Some(request)).await })).await.into_iter().collect::, Error>>()?.into_iter().map(Into::into).collect(); - user_games.insert(user.username.clone(), games); + gamenight.owned_games.0.insert(user.username.clone(), games); } - println!("{}\nwho: {}\nGames:\n{}", self.gamenight, Participants(&users), OwnedGames(&user_games)); - + println!("{}", gamenight); + let my_uid = state.get_user_id()?; let join_or_leave: Box + Send> = - if users.iter().map(|x| {x.id}).any(|x| x == my_uid) { - Box::new(Leave::new(self.gamenight.id)) + if gamenight.participants.0.iter().map(|x| {x.id}).any(|x| x == my_uid) { + Box::new(Leave::new(gamenight.id)) } - else { - Box::new(Join::new(self.gamenight.id)) + else { + Box::new(Join::new(gamenight.id)) }; let options: Vec + Send>> = vec![ @@ -71,9 +73,9 @@ impl<'a> Flow<'a> for ViewGamenight { } } -impl Display for ViewGamenight { +impl<'a> Display for ViewGamenight { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} {}", self.gamenight.name, self.gamenight.start_time.format("%d-%m-%Y %H:%M")) + write!(f, "{} {}", self.gamenight_select_data.name, self.gamenight_select_data.start_time.format("%d-%m-%Y %H:%M")) } } diff --git a/gamenight-database/src/game.rs b/gamenight-database/src/game.rs index 50330f8..7c9afb2 100644 --- a/gamenight-database/src/game.rs +++ b/gamenight-database/src/game.rs @@ -35,3 +35,10 @@ pub fn rename_game( .set(game::name.eq(&name)) .execute(conn)?) } + +pub fn remove_game( + conn: &mut DbConnection, + id: Uuid, +) -> Result { + Ok(diesel::delete(game::table.filter(game::id.eq(id))).execute(conn)?) +}