diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 16:27:35 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 16:27:35 +0200 |
| commit | 5a4c4b9fa0df891fcdd9beee18be0db4a45da701 (patch) | |
| tree | b467a1bd5706643b77962e7a82d651a803bfc436 /crates/turtle/src/atuin_client | |
| parent | chore(server): Simplify the database support (diff) | |
| download | atuin-5a4c4b9fa0df891fcdd9beee18be0db4a45da701.zip | |
chore(server): Remove the last remnants of the "hub" sync-server thingy
Diffstat (limited to 'crates/turtle/src/atuin_client')
| -rw-r--r-- | crates/turtle/src/atuin_client/auth.rs | 94 |
1 files changed, 26 insertions, 68 deletions
diff --git a/crates/turtle/src/atuin_client/auth.rs b/crates/turtle/src/atuin_client/auth.rs index b260d433..620e127e 100644 --- a/crates/turtle/src/atuin_client/auth.rs +++ b/crates/turtle/src/atuin_client/auth.rs @@ -1,4 +1,3 @@ -use async_trait::async_trait; use eyre::{Context, Result, bail}; use reqwest::{Url, header::USER_AGENT}; @@ -14,66 +13,19 @@ use crate::atuin_client::settings::Settings; static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION")); -/// Result of an auth operation that may require 2FA. -pub(crate) enum AuthResponse { - /// Operation succeeded; for login/register, contains the session token. - /// `auth_type` indicates the kind of token: `Some("hub")` for Hub API - /// tokens (prefixed `atapi_`), `Some("cli")` for legacy CLI session - /// tokens. `None` when the server didn't include the field (old servers). - Success { - session: String, - auth_type: Option<String>, - }, - /// Two-factor authentication is required; the caller should prompt for a - /// TOTP code and retry with it. - TwoFactorRequired, -} - -/// Result of a mutating account operation that may require 2FA. -pub(crate) enum MutateResponse { - /// Operation completed successfully. - Success, - /// Two-factor authentication is required; the caller should prompt for a - /// TOTP code and retry. - TwoFactorRequired, -} - -/// Abstraction over the legacy (Rust sync server) and Hub auth APIs. -/// -/// CLI commands use this trait so they don't need to know which backend is -/// active — they just prompt for input and call these methods. -#[async_trait] -pub(crate) trait AuthClient: Send + Sync { - /// Log in with username + password, optionally providing a TOTP code. - async fn login(&self, username: &str, password: &str) -> Result<AuthResponse>; - - /// Register a new account. - async fn register(&self, username: &str, email: &str, password: &str) -> Result<AuthResponse>; - - /// Change the account password, optionally providing a TOTP code. - async fn change_password( - &self, - current_password: &str, - new_password: &str, - totp_code: Option<&str>, - ) -> Result<MutateResponse>; - - /// Delete the account, requiring the current password and optionally a TOTP code. - async fn delete_account( - &self, - password: &str, - totp_code: Option<&str>, - ) -> Result<MutateResponse>; +/// Result of an auth operation +pub(crate) struct AuthResponse { + pub(crate) session: String, } /// Resolve the appropriate [`AuthClient`] for the current settings. -pub(crate) async fn auth_client(settings: &Settings) -> Box<dyn AuthClient> { - Box::new(LegacyAuthClient::new( +pub(crate) async fn auth_client(settings: &Settings) -> LegacyAuthClient { + LegacyAuthClient::new( &settings.sync_address, settings.session_token().await.ok(), settings.network_connect_timeout, settings.network_timeout, - )) as Box<dyn AuthClient> + ) } // --------------------------------------------------------------------------- @@ -125,9 +77,9 @@ impl LegacyAuthClient { } } -#[async_trait] -impl AuthClient for LegacyAuthClient { - async fn login(&self, username: &str, password: &str) -> Result<AuthResponse> { +impl LegacyAuthClient { + /// Log in with username + password, optionally providing a TOTP code. + pub(crate) async fn login(&self, username: &str, password: &str) -> Result<AuthResponse> { // The legacy server has no 2FA support; totp_code is ignored. let resp = api_client::login( &self.address, @@ -138,26 +90,31 @@ impl AuthClient for LegacyAuthClient { ) .await?; - Ok(AuthResponse::Success { + Ok(AuthResponse { session: resp.session, - auth_type: resp.auth.or(Some("cli".into())), }) } - async fn register(&self, username: &str, email: &str, password: &str) -> Result<AuthResponse> { + /// Register a new account. + pub(crate) async fn register( + &self, + username: &str, + email: &str, + password: &str, + ) -> Result<AuthResponse> { let resp = api_client::register(&self.address, username, email, password).await?; - Ok(AuthResponse::Success { + Ok(AuthResponse { session: resp.session, - auth_type: resp.auth.or(Some("cli".into())), }) } - async fn change_password( + /// Change the account password, optionally providing a TOTP code. + pub(crate) async fn change_password( &self, current_password: &str, new_password: &str, _totp_code: Option<&str>, - ) -> Result<MutateResponse> { + ) -> Result<()> { let client = self.authenticated_client()?; let url = make_url(&self.address, "/account/password")?; @@ -171,18 +128,19 @@ impl AuthClient for LegacyAuthClient { .await?; match resp.status().as_u16() { - 200 => Ok(MutateResponse::Success), + 200 => Ok(()), 401 => bail!("current password is incorrect"), 403 => bail!("invalid login details"), _ => bail!("unknown error"), } } - async fn delete_account( + /// Delete the account, requiring the current password and optionally a TOTP code. + pub(crate) async fn delete_account( &self, password: &str, _totp_code: Option<&str>, - ) -> Result<MutateResponse> { + ) -> Result<()> { let client = self.authenticated_client()?; let url = make_url(&self.address, "/account")?; @@ -193,7 +151,7 @@ impl AuthClient for LegacyAuthClient { .await?; match resp.status().as_u16() { - 200 => Ok(MutateResponse::Success), + 200 => Ok(()), 401 => bail!("password is incorrect"), 403 => bail!("invalid login details"), _ => bail!("unknown error"), |
