oxyde_cloud_cli/commands/
login.rs

1use crate::api_key::api_key_entry;
2use crate::commands::logout::logout;
3use anyhow::{Context, Result};
4use cliclack::log::remark;
5use cliclack::{input, intro, outro, outro_cancel, spinner};
6use oxyde_cloud_client::Client;
7
8pub async fn login() -> Result<()> {
9    intro("Login").context("Failed to show login intro")?;
10
11    let keyring_entry = api_key_entry().context("Failed to access keyring")?;
12
13    if keyring_entry.get_password().is_ok() {
14        outro("You're already logged in.").context("Failed to show outro message")?;
15        return Ok(());
16    }
17
18    remark("Get your API-Key from https://oxyde.cloud/dashboard/profile/api-key")
19        .context("Failed to show API key instructions")?;
20
21    let api_key: String = input("Paste your API key")
22        .placeholder("ABCD-efgh-IJKL-mnop")
23        .interact()
24        .context("Failed to get API key input")?;
25
26    let api_key = api_key.trim().to_string();
27
28    keyring_entry
29        .set_password(&api_key)
30        .context("Failed to store API key in keyring")?;
31
32    let spinner = spinner();
33    spinner.start("Logging in...");
34
35    match Client::new(api_key).login().await {
36        Ok(login_result) => {
37            spinner.stop("Done!");
38            outro(format!(
39                "You're now logged in as {}.",
40                login_result.username
41            ))
42            .context("Failed to show login success message")?;
43        }
44        Err(err) => {
45            logout().context("Failed to logout after login error")?;
46
47            spinner.error("Failed!");
48            outro_cancel(format!("Failed to login: {err}"))
49                .context("Failed to show login error message")?;
50        }
51    }
52
53    Ok(())
54}