wasmer_cli/commands/auth/
logout.rs

1use crate::{
2    commands::AsyncCliCommand,
3    config::{DEFAULT_PROD_REGISTRY, WasmerConfig, WasmerEnv},
4};
5use colored::Colorize;
6use is_terminal::IsTerminal;
7
8/// Log out from Wasmer
9#[derive(Debug, Clone, clap::Parser)]
10pub struct Logout {
11    #[clap(flatten)]
12    env: WasmerEnv,
13
14    /// Do not prompt for user input.
15    #[clap(long, default_value_t = !std::io::stdin().is_terminal())]
16    pub non_interactive: bool,
17
18    /// Whether or not to revoke the associated token
19    #[clap(long)]
20    pub revoke_token: bool,
21}
22
23#[async_trait::async_trait]
24impl AsyncCliCommand for Logout {
25    type Output = ();
26
27    async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
28        let registry = self.env.registry_endpoint()?.to_string();
29        let host_str = self
30            .env
31            .registry_public_url()
32            .map_err(|_| anyhow::anyhow!("No registry not specified!"))?
33            .host_str()
34            .unwrap()
35            .bold();
36
37        let client = self
38            .env
39            .client()
40            .map_err(|_| anyhow::anyhow!("Not logged into registry {host_str}"))?;
41
42        let user = wasmer_backend_api::query::current_user(&client)
43            .await
44            .map_err(|e| anyhow::anyhow!("Not logged into registry {host_str}: {e}"))?
45            .ok_or_else(|| anyhow::anyhow!("Not logged into registry {host_str}"))?;
46
47        let theme = dialoguer::theme::ColorfulTheme::default();
48        let prompt = dialoguer::Confirm::with_theme(&theme).with_prompt(format!(
49            "Log user {} out of registry {host_str}?",
50            user.username
51        ));
52
53        if prompt.interact()? || self.non_interactive {
54            let mut config = self.env.config()?;
55            let token = config
56                .registry
57                .get_login_token_for_registry(&registry)
58                .unwrap();
59            config.registry.remove_registry(&registry);
60            if config.registry.is_current_registry(&registry) {
61                if config.registry.tokens.is_empty() {
62                    _ = config
63                        .registry
64                        .set_current_registry(DEFAULT_PROD_REGISTRY)
65                        .await;
66                } else {
67                    let new_reg = config.registry.tokens[0].registry.clone();
68                    _ = config.registry.set_current_registry(&new_reg).await;
69                }
70            }
71            let path = WasmerConfig::get_file_location(self.env.dir());
72            config.save(path)?;
73
74            // Read it again..
75            //
76            let config = self.env.config()?;
77            if config
78                .registry
79                .get_login_token_for_registry(&registry)
80                .is_none()
81            {
82                println!(
83                    "User {} correctly logged out of registry {host_str}",
84                    user.username.bold()
85                );
86
87                let should_revoke = self.revoke_token || {
88                    let theme = dialoguer::theme::ColorfulTheme::default();
89                    dialoguer::Confirm::with_theme(&theme)
90                        .with_prompt("Revoke token?")
91                        .interact()?
92                };
93
94                if should_revoke {
95                    wasmer_backend_api::query::revoke_token(&client, token).await?;
96                    println!(
97                        "Token for user {} in registry {host_str} correctly revoked",
98                        user.username.bold()
99                    );
100                }
101            } else {
102                anyhow::bail!("Something went wrong! User is not logged out.")
103            }
104        } else {
105            println!("No action taken.");
106        }
107
108        Ok(())
109    }
110}