1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use clap::Parser;
#[cfg(not(test))]
use dialoguer::Input;
use wasmer_registry::WasmerConfig;

/// Subcommand for listing packages
#[derive(Debug, Clone, Parser)]
pub struct Login {
    /// Registry to log into (default: wapm.io)
    #[clap(long, default_value = "wapm.io")]
    pub registry: String,
    /// Login token
    #[clap(name = "TOKEN")]
    pub token: Option<String>,
}

impl Login {
    fn get_token_or_ask_user(&self) -> Result<String, std::io::Error> {
        match self.token.as_ref() {
            Some(s) => Ok(s.clone()),
            None => {
                let registry_host = wasmer_registry::format_graphql(&self.registry);
                let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default())
                    .extract(&registry_host)
                    .map_err(|e| {
                        std::io::Error::new(
                            std::io::ErrorKind::Other,
                            format!("Invalid registry for login {}: {e}", self.registry),
                        )
                    })?;
                let login_prompt = match (
                    registry_tld.domain.as_deref(),
                    registry_tld.suffix.as_deref(),
                ) {
                    (Some(d), Some(s)) => {
                        format!("Please paste the login token from https://{d}.{s}/settings/access-tokens")
                    }
                    _ => "Please paste the login token".to_string(),
                };
                #[cfg(test)]
                {
                    Ok(login_prompt)
                }
                #[cfg(not(test))]
                {
                    Input::new().with_prompt(&login_prompt).interact_text()
                }
            }
        }
    }

    /// execute [List]
    pub fn execute(&self) -> Result<(), anyhow::Error> {
        let token = self.get_token_or_ask_user()?;
        let wasmer_dir =
            WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?;
        match wasmer_registry::login::login_and_save_token(&wasmer_dir, &self.registry, &token)? {
            Some(s) => println!("Login for WAPM user {:?} saved", s),
            None => println!(
                "Error: no user found on registry {:?} with token {:?}. Token saved regardless.",
                self.registry, token
            ),
        }
        Ok(())
    }
}

#[test]
fn test_login_2() {
    let login = Login {
        registry: "wapm.dev".to_string(),
        token: None,
    };

    assert_eq!(
        login.get_token_or_ask_user().unwrap(),
        "Please paste the login token from https://wapm.dev/settings/access-tokens"
    );

    let login = Login {
        registry: "wapm.dev".to_string(),
        token: Some("abc".to_string()),
    };

    assert_eq!(login.get_token_or_ask_user().unwrap(), "abc");
}