Converted the Api to a Restful api.

This commit is contained in:
2026-01-22 22:51:03 +01:00
parent 79ba1e1b44
commit 9d3c5afb07
50 changed files with 2194 additions and 1939 deletions

View File

@@ -24,7 +24,7 @@ impl<'a> Flow<'a> for AddGame {
let add_game_request = AddGameRequestBody {
name
};
let game_id_response = state.api.game_post(Some(add_game_request)).await?;
let game_id_response = state.api.post_games(Some(add_game_request)).await?;
let own_flow = Own::new(Uuid::parse_str(&game_id_response.game_id)?);
return self.continue_with(state, &own_flow).await;

View File

@@ -31,7 +31,7 @@ impl<'a> Flow<'a> for AddGamenight {
.to_utc()
.to_rfc3339();
let add_gamenight = models::AddGamenightRequestBody::new(name, datetime);
state.api.post_gamenight(Some(add_gamenight)).await?;
state.api.post_gamenights(Some(add_gamenight)).await?;
clear_screen::clear();
return Ok((FlowOutcome::Successful, state))

View File

@@ -1,7 +1,7 @@
use std::{ffi::OsStr, fmt::Display};
use async_trait::async_trait;
use gamenight_api_client_rs::models::{authorize_location_request_body::Op::Grant, AddLocationRequestBody, AuthorizeLocationRequestBody};
use gamenight_api_client_rs::models::{AddLocationRequestBody, UserId};
use inquire::{Editor, Text};
@@ -44,15 +44,13 @@ impl<'a> Flow<'a> for AddLocation {
note
};
let location_id = state.api.location_post(Some(add_location_request)).await?;
let result = state.api.post_locations(Some(add_location_request)).await?;
let add_authorize_request = AuthorizeLocationRequestBody {
location_id: location_id.location_id.to_string(),
user_id: state.get_user_id()?.to_string(),
op: Grant
let user_id = UserId {
user_id: state.get_user_id()?.to_string()
};
state.api.location_authorize_post(Some(add_authorize_request)).await?;
state.api.post_location_authorized_users(&result.location_id, Some(user_id)).await?;
}
Ok((FlowOutcome::Cancelled, state))
}

View File

@@ -50,7 +50,7 @@ impl Connect {
pub async fn try_refresh_token_if_exists<'a>(&self, instance: &mut Instance, state: &'a mut GamenightState, instance_name: &String) -> Result<(bool, &'a mut GamenightState), FlowError> {
if let Some(token) = &instance.token {
let state = state.set_bearer_access_token(Some(token.clone()));
let result = state.api.post_token().await;
let result = state.api.post_refresh_token().await;
if let Ok(token) = result {
let instance = state.gamenight_configuration.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
instance.token = token.jwt_token.clone();

View File

@@ -1,7 +1,6 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::models::GameId;
use uuid::Uuid;
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
@@ -22,7 +21,7 @@ impl Disown {
#[async_trait]
impl<'a> Flow<'a> for Disown {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let _ = state.api.disown_post(Some(GameId{game_id: self.game_id.to_string()})).await?;
let _ = state.api.delete_game_owner(&self.game_id.to_string(), &state.get_user_id()?.to_string()).await?;
clear_screen::clear();
Ok((FlowOutcome::Successful, state))

View File

@@ -1,7 +1,7 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::models::GamenightId;
use gamenight_api_client_rs::models::UserId;
use uuid::Uuid;
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
@@ -22,7 +22,7 @@ impl Join {
#[async_trait]
impl<'a> Flow<'a> for Join {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let _ = state.api.join_post(Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
let _ = state.api.post_gamenight_participants(&self.gamenight_id.to_string(), Some(UserId{user_id: state.get_user_id()?.to_string()})).await?;
clear_screen::clear();
Ok((FlowOutcome::Successful, state))

View File

@@ -1,7 +1,6 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::models::GamenightId;
use uuid::Uuid;
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
@@ -22,7 +21,7 @@ impl Leave {
#[async_trait]
impl<'a> Flow<'a> for Leave {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let _ = state.api.leave_post(Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
let _ = state.api.delete_gamenight_participant(&self.gamenight_id.to_string(), &state.get_user_id()?.to_string()).await?;
clear_screen::clear();
Ok((FlowOutcome::Successful, state))

View File

@@ -21,7 +21,7 @@ impl ListGames {
#[async_trait]
impl<'a> Flow<'a> for ListGames {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let games = state.api.games_get().await?;
let games = state.api.get_games().await?;
let mut flows = games.into_iter().map(|game| -> Box<dyn Flow + Send> {
Box::new(ViewGame::new(game.into()))

View File

@@ -21,7 +21,7 @@ impl ListLocations {
#[async_trait]
impl<'a> Flow<'a> for ListLocations {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let locations = state.api.locations_get().await?;
let locations = state.api.get_locations().await?;
let mut flows = locations.into_iter().map(|location| -> Box<dyn Flow + Send> {
Box::new(ViewLocation::new(location.try_into().unwrap()))

View File

@@ -1,7 +1,7 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::models::{AuthorizeLocationRequestBody, LocationId, User};
use gamenight_api_client_rs::models::{User, UserId};
use inquire::MultiSelect;
use uuid::Uuid;
@@ -47,11 +47,9 @@ impl<'a> TryFrom<&'a User> for AuthorizeMultiSelectStruct<'a> {
#[async_trait]
impl<'a> Flow<'a> for LocationAuthorize {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let users = state.api.users_get().await?;
let location_id = LocationId {
location_id: self.location_id.to_string()
};
let authorized_user_ids = state.api.authorized_location_user_ids_get(Some(location_id)).await?;
let users = state.api.get_users().await?;
let authorized_user_ids = state.api.get_location_authorized_users(&self.location_id.to_string()).await?;
let authorized_user_ids : Vec<String> = authorized_user_ids.into_iter().map(|x| x.user_id).collect();
let options: Vec<AuthorizeMultiSelectStruct> = users.iter().map(|x| {x.try_into()}).collect::<Result<Vec<AuthorizeMultiSelectStruct>, FlowError>>()?;
@@ -66,25 +64,14 @@ impl<'a> Flow<'a> for LocationAuthorize {
if let Some(selections) = &selections {
for selection in selections {
let user_id = UserId { user_id: selection.id.to_string() };
if authorized_users.iter().find(|x| {x.id == selection.id.to_string()}).is_none() {
state.api.location_authorize_post(Some(
AuthorizeLocationRequestBody {
location_id: self.location_id.to_string(),
user_id: selection.id.to_string(),
op: gamenight_api_client_rs::models::authorize_location_request_body::Op::Grant
}
)).await?
state.api.post_location_authorized_users(&self.location_id.to_string(), Some(user_id)).await?
}
}
for authorized_user in authorized_users {
if selections.iter().find(|x| {x.id.to_string() == authorized_user.id}).is_none() {
state.api.location_authorize_post(Some(
AuthorizeLocationRequestBody {
location_id: self.location_id.to_string(),
user_id: authorized_user.id.to_string(),
op: gamenight_api_client_rs::models::authorize_location_request_body::Op::Revoke
}
)).await?
state.api.delete_location_authorized_user(&self.location_id.to_string(), &authorized_user.id.to_string()).await?
}
}
}

View File

@@ -26,7 +26,7 @@ impl<'a> Flow<'a> for Login {
let login = models::Login::new(username, password);
let result = state.api.get_token(Some(login)).await?;
let result = state.api.post_token(Some(login)).await?;
clear_screen::clear();
if let Some(token) = result.jwt_token {

View File

@@ -3,7 +3,7 @@ use std::fmt::Display;
use super::{Flow, FlowError, FlowOutcome, FlowResult, GamenightState};
use crate::domain::location_select_data::LocationSelectData;
use async_trait::async_trait;
use gamenight_api_client_rs::models::OwnGameRequestBody;
use gamenight_api_client_rs::models::OwnGame;
use inquire::{Confirm, Select};
use uuid::Uuid;
@@ -24,8 +24,8 @@ impl Own {
impl<'a> Flow<'a> for Own {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let mut own_game_request = OwnGameRequestBody {
game_id: self.game_id.to_string(),
let mut own_game_request = OwnGame {
user_id: state.get_user_id()?.to_string(),
location_id: None
};
@@ -33,13 +33,13 @@ impl<'a> Flow<'a> for Own {
if owned {
if let Some(willing_to_travel) = Confirm::new("Are you willing to travel with this game?").prompt_skippable()? {
if !willing_to_travel {
let locations = state.api.locations_get().await?.iter().map(|x| { x.try_into() }).collect::<Result<Vec<LocationSelectData>, FlowError>>()?;
let locations = state.api.get_locations().await?.iter().map(|x| { x.try_into() }).collect::<Result<Vec<LocationSelectData>, FlowError>>()?;
if let Some(location) = Select::new("What location can this game be played?", locations).prompt_skippable()? {
own_game_request.location_id = Some(location.id.to_string());
}
}
}
let _ = state.api.own_post(Some(own_game_request)).await?;
let _ = state.api.post_game_owners(&self.game_id.to_string(), Some(own_game_request)).await?;
}
}

View File

@@ -1,7 +1,6 @@
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;
@@ -22,10 +21,7 @@ impl RemoveGame {
#[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()
};
state.api.game_delete(Some(req)).await?;
state.api.delete_game(&self.game.id.to_string()).await?;
//Hack to return to right stack item, skipping detail view that doesn't exist.
Ok((FlowOutcome::Abort, state))
}

View File

@@ -1,7 +1,7 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::models::RenameGameRequestBody;
use gamenight_api_client_rs::models::EditGameRequestBody;
use inquire::Text;
use crate::domain::game::Game;
@@ -28,11 +28,11 @@ impl<'a> Flow<'a> for RenameGame {
.with_initial_value(&self.game.name)
.prompt_skippable()?
{
let req = RenameGameRequestBody {
let req = EditGameRequestBody {
id: self.game.id.to_string(),
name
};
state.api.rename_game_post(Some(req)).await?;
state.api.put_game(&req.id.clone(), Some(req)).await?;
return Ok((FlowOutcome::Successful, state))
}

View File

@@ -1,11 +1,9 @@
use gamenight_api_client_rs::models::{GameId, UserId};
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::*;
use crate::flows::remove_game::RemoveGame;
use crate::{domain::game::Game, flows::{disown::Disown, exit::Exit, own::Own, rename_game::RenameGame}};
#[derive(Clone)]
pub struct ViewGame {
@@ -23,14 +21,10 @@ impl ViewGame {
#[async_trait]
impl<'a> Flow<'a> for ViewGame {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let game_id = GameId{ game_id: self.game.id.to_string() };
let game: Game = state.api.game_get(Some(game_id)).await?.into();
let game: Game = state.api.get_game(&self.game.id.to_string()).await?.into();
println!("{}", game);
let my_uid = state.get_user_id()?;
let request = UserId{ user_id: my_uid.to_string() };
let owned_games: Vec<Uuid> = state.api.owned_games_get(Some(request)).await?
let owned_games: Vec<Uuid> = state.api.get_user_owned_games(&state.get_user_id()?.to_string()).await?
.iter().map(|x| -> Result<Uuid, FlowError> {
Ok(Uuid::parse_str(&x.game_id)?)
}).collect::<Result<Vec<Uuid>, FlowError>>()?;

View File

@@ -1,7 +1,7 @@
use crate::domain::gamenight::Gamenight;
use std::collections::HashMap;
use gamenight_api_client_rs::models::{GameId, GamenightId, LocationId, OwnedGame, UserId};
use gamenight_api_client_rs::models::OwnedGame;
use inquire::Select;
use super::*;
@@ -29,30 +29,29 @@ impl<'a> Flow<'a> for ViewGamenight {
start_time: self.gamenight_select_data.start_time,
name: self.gamenight_select_data.name.clone(),
location: None,
organizer: state.api.user_get(Some(UserId{user_id: self.gamenight_select_data.owner_id.to_string()})).await?.try_into()?,
organizer: state.api.get_user(&self.gamenight_select_data.owner_id.to_string()).await?.try_into()?,
participants: Participants(vec![]),
owned_games: OwnedGames(HashMap::new())
};
gamenight.location = match self.gamenight_select_data.location_id {
None => None,
Some(l) => Some(state.api.location_get(Some(LocationId{location_id: l.to_string()})).await?.try_into()?)
Some(l) => Some(state.api.get_location(&l.to_string()).await?.try_into()?)
};
let participants = state.api.participants_get(Some(GamenightId{gamenight_id: gamenight.id.to_string()})).await?;
let participants = state.api.get_gamenight_participants(&gamenight.id.to_string()).await?;
for participant in participants.participants.iter() {
gamenight.participants.0.push(state.api.user_get(Some(UserId{user_id: participant.clone()})).await?.try_into()?);
gamenight.participants.0.push(state.api.get_user(&participant).await?.try_into()?);
}
for user in &gamenight.participants.0 {
let request = UserId{ user_id: user.id.to_string() };
let owned_games_refs: Vec<OwnedGame> = state.api.owned_games_get(Some(request)).await?;
let owned_games_refs: Vec<OwnedGame> = state.api.get_user_owned_games(&user.id.to_string()).await?;
let mut owned_games = vec![];
for owned_games_ref in owned_games_refs {
let game = state.api.game_get(Some(GameId{ game_id: owned_games_ref.game_id.clone()})).await?.into();
let game = state.api.get_game(&owned_games_ref.game_id).await?.into();
let location = match owned_games_ref.location_id {
None => None,
Some(x) => Some(state.api.location_get(Some(LocationId{location_id: x})).await?.try_into()?)
Some(x) => Some(state.api.get_location(&x).await?.try_into()?)
};
owned_games.push((game, location));
}