forked from Roflin/gamenight
139 lines
4.7 KiB
Rust
139 lines
4.7 KiB
Rust
use std::fmt::Display;
|
|
|
|
use async_trait::async_trait;
|
|
use gamenight_api_client_rs::apis::configuration::Configuration;
|
|
use inquire::Text;
|
|
|
|
use crate::{domain::config::{Config, Instance}, flows::{gamenight_menu::GamenightMenu, login::Login, FlowError}};
|
|
|
|
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
|
|
|
|
#[derive(Clone)]
|
|
pub struct Connect {
|
|
instance: Option<Instance>
|
|
}
|
|
|
|
impl Connect {
|
|
pub fn to(instance: Instance) -> Self {
|
|
Self {
|
|
instance: Some(instance)
|
|
}
|
|
}
|
|
|
|
pub fn new() -> Self {
|
|
Self {
|
|
instance: None
|
|
}
|
|
}
|
|
|
|
pub fn prompt_new_instance(&self, config: &Config) -> Result<Option<Instance>, FlowError> {
|
|
let instance_name: String;
|
|
loop {
|
|
if let Some(name) = Text::new("Name this instance:").prompt_skippable()? {
|
|
if config.instances.iter().find(|x| x.name == name).is_none() {
|
|
instance_name = name;
|
|
break;
|
|
} else {
|
|
clear_screen::clear();
|
|
println!("Name already in use, please provide a unique name");
|
|
}
|
|
}
|
|
else {
|
|
return Ok(None);
|
|
}
|
|
}
|
|
if let Some(url) = Text::new("What is the server URL: ").prompt_skippable()? {
|
|
Ok(Some(Instance::new(instance_name, url)))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
|
|
}
|
|
|
|
pub async fn try_refresh_token_if_exists(&self, instance: &mut Instance, api_configuration: &mut Configuration, config: &mut Config, instance_name: &String) -> Result<bool, FlowError> {
|
|
if let Some(token) = &instance.token {
|
|
api_configuration.bearer_access_token = Some(token.clone());
|
|
let result = gamenight_api_client_rs::apis::default_api::post_token(api_configuration).await;
|
|
if let Ok(token) = result {
|
|
let instance = config.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
|
instance.token = token.jwt_token.clone();
|
|
api_configuration.bearer_access_token = token.jwt_token.clone();
|
|
Config::save(&config)?;
|
|
Ok(true)
|
|
}
|
|
else {
|
|
Ok(false)
|
|
}
|
|
} else {
|
|
Ok(false)
|
|
}
|
|
}
|
|
|
|
pub fn update_state_on_logon(&self, instance: &mut Instance, api_configuration: &mut Configuration, config: &mut Config, instance_name: &String) -> Result<(), FlowError> {
|
|
if self.instance.is_none() {
|
|
instance.token = Some(api_configuration.bearer_access_token.clone().unwrap());
|
|
config.instances.push(instance.clone());
|
|
}
|
|
else {
|
|
let instance = config.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
|
instance.token = Some(api_configuration.bearer_access_token.clone().unwrap());
|
|
}
|
|
config.last_instance = Some(instance_name.clone());
|
|
|
|
Config::save(&config)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl<'a> Flow<'a> for Connect {
|
|
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
|
let mut instance = if let Some(instance) = self.instance.clone() {
|
|
instance
|
|
} else {
|
|
if let Some(instance) = self.prompt_new_instance(&state.gamenight_configuration)? {
|
|
instance
|
|
}
|
|
else {
|
|
return Ok((FlowOutcome::Cancelled, state));
|
|
}
|
|
};
|
|
|
|
let instance_name = instance.name.clone();
|
|
state.api_configuration.base_path = instance.url.clone();
|
|
|
|
if self.try_refresh_token_if_exists(&mut instance, &mut state.api_configuration, &mut state.gamenight_configuration, &instance_name).await? {
|
|
let gamenight_menu_flow = GamenightMenu::new();
|
|
gamenight_menu_flow.run(state).await
|
|
}
|
|
else {
|
|
let login_flow = Login::new();
|
|
let (outcome, state) = login_flow.run(state).await?;
|
|
|
|
if outcome == FlowOutcome::Successful {
|
|
self.update_state_on_logon(&mut instance, &mut state.api_configuration, &mut state.gamenight_configuration, &instance_name)?;
|
|
|
|
let gamenight_menu_flow = GamenightMenu::new();
|
|
gamenight_menu_flow.run(state).await
|
|
}
|
|
else {
|
|
Ok((outcome, state))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
impl Display for Connect {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(instance) = &self.instance {
|
|
write!(f, "Connect to: {}", instance.name)
|
|
} else {
|
|
write!(f, "Connect")
|
|
}
|
|
|
|
}
|
|
} |