| 1 | use { |
| 2 | crate::{cli::AuthCommand, config, context::Ctx, ui}, |
| 3 | anyhow::{anyhow, Result}, |
| 4 | sigit_si_api::{account::incomplete_reason, models::AccountStatus}, |
| 5 | }; |
| 6 | |
| 7 | pub async fn run(ctx: &Ctx, command: AuthCommand) -> Result<()> { |
| 8 | match command { |
| 9 | AuthCommand::Login { email } => login(ctx, email).await, |
| 10 | AuthCommand::Logout => logout(ctx).await, |
| 11 | AuthCommand::Status => status(ctx).await, |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | async fn login(ctx: &Ctx, email: Option<String>) -> Result<()> { |
| 16 | let email = match email { |
| 17 | Some(email) => email, |
| 18 | None => ui::prompt::text("Email")?, |
| 19 | }; |
| 20 | let password = ui::prompt::password("Password")?; |
| 21 | |
| 22 | match ctx.client.sign_in(&email, &password).await? { |
| 23 | AccountStatus::Ready { access_token } => { |
| 24 | let path = config::write_token(ctx.environment, &access_token)?; |
| 25 | ui::success(format!( |
| 26 | "Signed in as {}. Token saved to {}.", |
| 27 | ui::highlight(&email), |
| 28 | path.display() |
| 29 | )); |
| 30 | Ok(()) |
| 31 | } |
| 32 | AccountStatus::NotFound => Err(anyhow!( |
| 33 | "No sigit.si account found for {email}. Sign up at https://sigit.si/auth/signup." |
| 34 | )), |
| 35 | AccountStatus::Incomplete { status } => Err(anyhow!("{}", incomplete_reason(status))), |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | async fn logout(ctx: &Ctx) -> Result<()> { |
| 40 | // A token file surviving from a previous, now-unauthenticated session |
| 41 | // shouldn't block sign-out — clear it locally either way. |
| 42 | if ctx.client.token().is_some() { |
| 43 | let _ = ctx.client.sign_out().await; |
| 44 | } |
| 45 | config::clear_token(ctx.environment)?; |
| 46 | ui::success("Signed out."); |
| 47 | Ok(()) |
| 48 | } |
| 49 | |
| 50 | async fn status(ctx: &Ctx) -> Result<()> { |
| 51 | if ctx.client.token().is_none() { |
| 52 | println!("Not signed in to {}. Run `si auth login`.", ctx.environment); |
| 53 | return Ok(()); |
| 54 | } |
| 55 | |
| 56 | match ctx.client.user().await { |
| 57 | Ok(user) => ui::emit(ctx.json, &user, |user| { |
| 58 | println!( |
| 59 | "Signed in to {} as {} <{}>.", |
| 60 | ctx.environment, |
| 61 | ui::highlight(&user.username), |
| 62 | user.email |
| 63 | ); |
| 64 | }), |
| 65 | Err(e) if e.is_auth_failure() => { |
| 66 | config::clear_token(ctx.environment)?; |
| 67 | Err(anyhow!( |
| 68 | "Your session has expired. Run `si auth login` to sign in again." |
| 69 | )) |
| 70 | } |
| 71 | Err(e) => Err(e.into()), |
| 72 | } |
| 73 | } |