Skip to content

Commit

Permalink
feature: Add invalidate flag to logout
Browse files Browse the repository at this point in the history
  • Loading branch information
Zertsov committed Feb 21, 2024
1 parent df29695 commit e2b2f06
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 11 deletions.
15 changes: 15 additions & 0 deletions crates/turborepo-api-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub trait CacheClient {
#[async_trait]
pub trait TokenClient {
async fn get_metadata(&self, token: &str) -> Result<ResponseTokenMetadata>;
async fn delete_token(&self, token: &str) -> Result<()>;
}

#[derive(Clone)]
Expand Down Expand Up @@ -433,6 +434,20 @@ impl TokenClient for APIClient {
let body = response.json::<Response>().await?;
Ok(body.metadata)
}

/// Invalidates the given token on the server.
async fn delete_token(&self, token: &str) -> Result<()> {
let url = self.make_url("/v3/user/tokens/current")?;
let request_builder = self
.client
.delete(url)
.header("User-Agent", self.user_agent.clone())
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json");
let response = retry::make_retryable_request(request_builder).await?;
response.error_for_status()?;
Ok(())
}
}

impl APIClient {
Expand Down
4 changes: 4 additions & 0 deletions crates/turborepo-auth/src/auth/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub async fn login<T: Client + TokenClient + CacheClient>(
ui::print_cli_authorized(user_email, &ui);
}
};

// Check if passed in token exists first.
if !force {
if let Some(token) = existing_token {
Expand Down Expand Up @@ -291,6 +292,9 @@ mod tests {
created_at: 123456,
})
}
async fn delete_token(&self, _token: &str) -> turborepo_api_client::Result<()> {
Ok(())
}
}

#[async_trait]
Expand Down
22 changes: 17 additions & 5 deletions crates/turborepo-auth/src/auth/logout.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
use tracing::error;
use turborepo_api_client::Client;
use turbopath::AbsoluteSystemPathBuf;
use turborepo_api_client::TokenClient;
use turborepo_ui::{cprintln, GREY};

use crate::{Error, LogoutOptions};
use crate::{Error, LogoutOptions, Token};

pub fn logout<T: Client>(options: &LogoutOptions<T>) -> Result<(), Error> {
if let Err(err) = remove_token(options) {
pub async fn logout<T: TokenClient>(options: &LogoutOptions<'_, T>) -> Result<(), Error> {
let LogoutOptions {
ui,
api_client,
path,
invalidate,
} = *options;

if invalidate {
return Token::from_file(path)?.invalidate(api_client).await;
}

if let Err(err) = remove_token(path) {
error!("could not logout. Something went wrong: {}", err);
return Err(err);
}

cprintln!(options.ui, GREY, ">>> Logged out");
cprintln!(ui, GREY, ">>> Logged out");
Ok(())
}

Expand Down
3 changes: 3 additions & 0 deletions crates/turborepo-auth/src/auth/sso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ mod tests {
created_at: 123456,
})
}
async fn delete_token(&self, _token: &str) -> turborepo_api_client::Result<()> {
Ok(())
}
}

#[async_trait]
Expand Down
11 changes: 11 additions & 0 deletions crates/turborepo-auth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod ui;
pub use auth::*;
pub use error::Error;
pub use login_server::*;
use turbopath::AbsoluteSystemPathBuf;
use turborepo_api_client::{CacheClient, Client, TokenClient};
use turborepo_vercel_api::{token::ResponseTokenMetadata, User};

Expand All @@ -38,6 +39,10 @@ impl Token {
pub fn existing(token: String) -> Self {
Self::Existing(token)
}
pub fn from_file(path: &AbsoluteSystemPathBuf) -> Result<Self, Error> {
let token = std::fs::read_to_string(path)?;
Ok(Self::Existing(token))
}

/// Checks if the token is still valid. The checks ran are:
/// 1. If the token is active.
Expand Down Expand Up @@ -187,6 +192,12 @@ impl Token {
.await
.map_err(Error::from)
}

/// Invalidates the token on the server.
pub async fn invalidate<T: TokenClient>(&self, client: &T) -> Result<(), Error> {
client.delete_token(self.into_inner()).await?;
Ok(())
}
/// Returns the underlying token string.
pub fn into_inner(&self) -> &str {
match self {
Expand Down
17 changes: 12 additions & 5 deletions crates/turborepo-lib/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,11 @@ pub enum Command {
force: bool,
},
/// Logout to your Vercel account
Logout {},
Logout {
/// Invalidate the token on the server
#[clap(long)]
invalidate: bool,
},
/// Prepare a subset of your monorepo.
Prune {
#[clap(hide = true, long)]
Expand Down Expand Up @@ -1110,12 +1114,15 @@ pub async fn run(

Ok(0)
}
Command::Logout { .. } => {
Command::Logout { invalidate } => {
let event = CommandEventBuilder::new("logout").with_parent(&root_telemetry);
event.track_call();
let invalidate = *invalidate;

let mut base = CommandBase::new(cli_args, repo_root, version, ui);
let event_child = event.child();
logout::logout(&mut base, event_child)?;

logout::logout(&mut base, invalidate, event_child).await?;

Ok(0)
}
Expand Down Expand Up @@ -2003,7 +2010,7 @@ mod test {
assert_eq!(
Args::try_parse_from(["turbo", "logout"]).unwrap(),
Args {
command: Some(Command::Logout {}),
command: Some(Command::Logout { invalidate: false }),
..Args::default()
}
);
Expand All @@ -2013,7 +2020,7 @@ mod test {
command_args: vec![],
global_args: vec![vec!["--cwd", "../examples/with-yarn"]],
expected_output: Args {
command: Some(Command::Logout {}),
command: Some(Command::Logout { invalidate: false }),
cwd: Some(Utf8PathBuf::from("../examples/with-yarn")),
..Args::default()
},
Expand Down
8 changes: 7 additions & 1 deletion crates/turborepo-lib/src/commands/logout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ use turborepo_telemetry::events::command::CommandEventBuilder;

use crate::{cli::Error, commands::CommandBase};

pub fn logout(base: &mut CommandBase, _telemetry: CommandEventBuilder) -> Result<(), Error> {
pub async fn logout(
base: &mut CommandBase,
invalidate: bool,
_telemetry: CommandEventBuilder,
) -> Result<(), Error> {
auth_logout(&LogoutOptions {
ui: &base.ui,
api_client: &base.api_client()?,
path: &base.global_config_path()?,
invalidate,
})
.await
.map_err(Error::from)
}
1 change: 1 addition & 0 deletions turborepo-tests/integration/tests/turbo-help.t
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ Test help flag for logout command
Usage: turbo(\.exe)? logout \[OPTIONS\] (re)

Options:
--invalidate Invalidate the token on the server
--version
--skip-infer Skip any attempts to infer which version of Turbo the project is configured to use
--no-update-notifier Disable the turbo update notification
Expand Down

0 comments on commit e2b2f06

Please sign in to comment.