Skip to main content

blue_build/commands/
login.rs

1use std::io::{self, Read};
2
3use blue_build_process_management::drivers::{BuildDriver, Driver, DriverArgs, SigningDriver};
4use blue_build_utils::{
5    credentials::{Credentials, CredentialsArgs},
6    secret::SecretValue,
7};
8use clap::Args;
9use miette::{IntoDiagnostic, Result, bail};
10use requestty::questions;
11
12use super::BlueBuildCommand;
13
14#[derive(Debug, Clone, Args)]
15pub struct LoginCommand {
16    /// The server to login to.
17    server: String,
18
19    /// The password to login with.
20    ///
21    /// Cannot be used with `--password-stdin`.
22    #[arg(group = "pass", long, short)]
23    password: Option<String>,
24
25    /// Read password from stdin,
26    ///
27    /// Cannot be used with `--password/-p`
28    #[arg(group = "pass", long)]
29    password_stdin: bool,
30
31    /// The username to login with
32    #[arg(long, short)]
33    username: Option<String>,
34
35    #[clap(flatten)]
36    drivers: DriverArgs,
37}
38
39impl BlueBuildCommand for LoginCommand {
40    fn try_run(&mut self) -> miette::Result<()> {
41        Driver::init(self.drivers);
42
43        Credentials::init(
44            CredentialsArgs::builder()
45                .registry(&self.server)
46                .username(self.get_username()?)
47                .password(self.get_password()?)
48                .build(),
49        );
50
51        Driver::login(&self.server)?;
52        Driver::signing_login(&self.server)?;
53
54        Ok(())
55    }
56}
57
58impl LoginCommand {
59    fn get_username(&self) -> Result<String> {
60        Ok(if let Some(ref username) = self.username {
61            username.clone()
62        } else if !self.password_stdin {
63            let questions = questions! [ inline
64                Input {
65                    name: "username",
66                },
67            ];
68
69            requestty::prompt(questions)
70                .into_diagnostic()?
71                .get("username")
72                .unwrap()
73                .as_string()
74                .unwrap()
75                .to_string()
76        } else {
77            bail!("Cannot prompt for username when using `--password-stdin`");
78        })
79    }
80
81    fn get_password(&self) -> Result<SecretValue> {
82        Ok(if let Some(ref password) = self.password {
83            password.clone().into()
84        } else if self.password_stdin {
85            let mut password = String::new();
86            io::stdin()
87                .read_to_string(&mut password)
88                .into_diagnostic()?;
89            password.into()
90        } else {
91            let questions = questions! [ inline
92                Password {
93                    name: "password",
94                }
95            ];
96
97            requestty::prompt(questions)
98                .into_diagnostic()?
99                .get("password")
100                .unwrap()
101                .as_string()
102                .unwrap()
103                .to_string()
104                .into()
105        })
106    }
107}