diff --git a/api-client/src/lib.rs b/api-client/src/lib.rs index cd642bdc0..f923525b9 100644 --- a/api-client/src/lib.rs +++ b/api-client/src/lib.rs @@ -103,7 +103,7 @@ impl ShuttleApiClient { .context("parsing name check response") } - pub async fn get_current_user(&self) -> Result { + pub async fn get_current_user_beta(&self) -> Result { self.get_json("/users/me".to_owned()).await } diff --git a/api-client/src/util.rs b/api-client/src/util.rs index 978a54cb8..d04c97099 100644 --- a/api-client/src/util.rs +++ b/api-client/src/util.rs @@ -14,27 +14,26 @@ pub trait ToJson { impl ToJson for reqwest::Response { async fn to_json(self) -> Result { let status_code = self.status(); - let full = self.bytes().await?; + let bytes = self.bytes().await?; + let string = String::from_utf8(bytes.to_vec()) + .unwrap_or_else(|_| format!("[{} bytes]", bytes.len())); #[cfg(feature = "tracing")] - tracing::trace!( - response = %String::from_utf8(full.to_vec()).unwrap_or_else(|_| format!("[{} bytes]", full.len())), - "parsing response to json" - ); + tracing::trace!(response = string, "Parsing response to JSON"); if matches!( status_code, StatusCode::OK | StatusCode::SWITCHING_PROTOCOLS ) { - serde_json::from_slice(&full).context("failed to parse a successful response") + serde_json::from_str(&string).context("failed to parse a successful response") } else { #[cfg(feature = "tracing")] - tracing::trace!("parsing response to common error"); + tracing::trace!("Parsing response to common error"); - let res: ApiError = match serde_json::from_slice(&full) { + let res: ApiError = match serde_json::from_str(&string) { Ok(res) => res, _ => ApiError { - message: "Failed to parse response from the server.".to_string(), + message: format!("Failed to parse response from the server:\n{}", string), status_code: status_code.as_u16(), }, }; diff --git a/cargo-shuttle/src/args.rs b/cargo-shuttle/src/args.rs index adcddda03..427e83105 100644 --- a/cargo-shuttle/src/args.rs +++ b/cargo-shuttle/src/args.rs @@ -122,6 +122,8 @@ pub enum Command { Resource(ResourceCommand), /// Remove cargo build artifacts in the Shuttle environment Clean, + /// BETA: Show info about your Shuttle account + Account, /// Login to the Shuttle platform Login(LoginArgs), /// Log out of the Shuttle platform diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index 8f7491d9e..18a21f8a6 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -150,7 +150,10 @@ impl Shuttle { return Ok(CommandOutcome::Ok); } eprintln!("INFO: Using beta platform API"); - } else if matches!(args.cmd, Command::Deployment(DeploymentCommand::Stop)) { + } else if matches!( + args.cmd, + Command::Deployment(DeploymentCommand::Stop) | Command::Account + ) { eprintln!("This command is not supported on the legacy platform."); return Ok(CommandOutcome::Ok); } @@ -194,6 +197,7 @@ impl Shuttle { | Command::Deploy(..) | Command::Status | Command::Logs { .. } + | Command::Account | Command::Login(..) | Command::Logout(..) | Command::Deployment(..) @@ -233,6 +237,7 @@ impl Shuttle { GenerateCommand::Manpage => self.generate_manpage(), GenerateCommand::Shell { shell, output } => self.complete(shell, output), }, + Command::Account => self.account().await, Command::Login(login_args) => self.login(login_args, args.offline).await, Command::Logout(logout_args) => self.logout(logout_args).await, Command::Feedback => self.feedback(), @@ -736,6 +741,24 @@ impl Shuttle { Ok(CommandOutcome::Ok) } + async fn account(&self) -> Result { + let client = self.client.as_ref().unwrap(); + let user = client.get_current_user_beta().await?; + println!("{}", "Account info:".bold()); + println!(" User Id: {}", user.id); + println!(" Username: {}", user.name); + println!(" Account tier: {}", user.account_tier); + println!(" Subscriptions:"); + for sub in user.subscriptions { + println!( + " - {}: Type: {}, Quantity: {}, Created: {}, Updated: {}", + sub.id, sub.r#type, sub.quantity, sub.created_at, sub.updated_at, + ); + } + + Ok(CommandOutcome::Ok) + } + /// Log in with the given API key or after prompting the user for one. async fn login(&mut self, login_args: LoginArgs, offline: bool) -> Result { let api_key_str = match login_args.api_key { @@ -768,7 +791,7 @@ impl Shuttle { eprintln!("INFO: Skipping API key verification"); } else { let u = client - .get_current_user() + .get_current_user_beta() .await .context("failed to check API key validity")?; println!("Logged in as {} ({})", u.name.bold(), u.id.bold()); diff --git a/scripts/local-admin.sh b/scripts/local-admin.sh index 5730e3ab8..e734f453c 100755 --- a/scripts/local-admin.sh +++ b/scripts/local-admin.sh @@ -7,6 +7,7 @@ key="dh9z58jttoes3qvt" # arbitrary test key export SHUTTLE_API_KEY=$key export SHUTTLE_API="http://localhost:8001" +unset SHUTTLE_BETA export PS1="(shuttle: local admin key) $(echo $PS1 | sed -e "s/(shuttle: .*) //")" docker compose --file docker-compose.rendered.yml --project-name shuttle-dev exec auth /usr/local/bin/shuttle-auth --db-connection-uri=postgres://postgres:postgres@control-db init-admin --user-id admin --key $key diff --git a/scripts/production.sh b/scripts/production.sh index 2ea604406..54c20a90f 100755 --- a/scripts/production.sh +++ b/scripts/production.sh @@ -6,4 +6,5 @@ export SHUTTLE_API="https://api.shuttle.rs" unset SHUTTLE_API_KEY +unset SHUTTLE_BETA export PS1="(shuttle: production) $(echo $PS1 | sed -e "s/(shuttle: .*) //")" diff --git a/scripts/unstable.sh b/scripts/unstable.sh index 47ee5afdb..7e2107196 100755 --- a/scripts/unstable.sh +++ b/scripts/unstable.sh @@ -5,4 +5,5 @@ export SHUTTLE_API="https://api.unstable.shuttle.rs" unset SHUTTLE_API_KEY +unset SHUTTLE_BETA export PS1="(shuttle: unstable) $(echo $PS1 | sed -e "s/(shuttle: .*) //")"