diff options
Diffstat (limited to 'atuin-client/src/api_client.rs')
-rw-r--r-- | atuin-client/src/api_client.rs | 120 |
1 files changed, 110 insertions, 10 deletions
diff --git a/atuin-client/src/api_client.rs b/atuin-client/src/api_client.rs index db2802c3..a8ce7b27 100644 --- a/atuin-client/src/api_client.rs +++ b/atuin-client/src/api_client.rs @@ -1,15 +1,24 @@ +use std::collections::HashMap; + use chrono::Utc; -use eyre::Result; -use reqwest::header::{HeaderMap, AUTHORIZATION}; -use reqwest::Url; +use eyre::{eyre, Result}; +use reqwest::header::{HeaderMap, AUTHORIZATION, USER_AGENT}; +use reqwest::{StatusCode, Url}; use sodiumoxide::crypto::secretbox; -use atuin_common::api::{AddHistoryRequest, CountResponse, SyncHistoryResponse}; +use atuin_common::api::{ + AddHistoryRequest, CountResponse, LoginResponse, RegisterResponse, SyncHistoryResponse, +}; use atuin_common::utils::hash_str; -use crate::encryption::decrypt; +use crate::encryption::{decode_key, decrypt}; use crate::history::History; +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +// TODO: remove all references to the encryption key from this +// It should be handled *elsewhere* + pub struct Client<'a> { sync_addr: &'a str, token: &'a str, @@ -17,14 +26,70 @@ pub struct Client<'a> { client: reqwest::Client, } +pub fn register( + address: &str, + username: &str, + email: &str, + password: &str, +) -> Result<RegisterResponse> { + let mut map = HashMap::new(); + map.insert("username", username); + map.insert("email", email); + map.insert("password", password); + + let url = format!("{}/user/{}", address, username); + let resp = reqwest::blocking::get(url)?; + + if resp.status().is_success() { + return Err(eyre!("username already in use")); + } + + let url = format!("{}/register", address); + let client = reqwest::blocking::Client::new(); + let resp = client + .post(url) + .header(USER_AGENT, format!("atuin/{}", VERSION)) + .json(&map) + .send()?; + + if !resp.status().is_success() { + return Err(eyre!("failed to register user")); + } + + let session = resp.json::<RegisterResponse>()?; + Ok(session) +} + +pub fn login(address: &str, username: &str, password: &str) -> Result<LoginResponse> { + let mut map = HashMap::new(); + map.insert("username", username); + map.insert("password", password); + + let url = format!("{}/login", address); + let client = reqwest::blocking::Client::new(); + + let resp = client + .post(url) + .header(USER_AGENT, format!("atuin/{}", VERSION)) + .json(&map) + .send()?; + + if resp.status() != reqwest::StatusCode::OK { + return Err(eyre!("invalid login details")); + } + + let session = resp.json::<LoginResponse>()?; + Ok(session) +} + impl<'a> Client<'a> { - pub fn new(sync_addr: &'a str, token: &'a str, key: secretbox::Key) -> Self { - Client { + pub fn new(sync_addr: &'a str, token: &'a str, key: String) -> Result<Self> { + Ok(Client { sync_addr, token, - key, + key: decode_key(key)?, client: reqwest::Client::new(), - } + }) } pub async fn count(&self) -> Result<i64> { @@ -36,7 +101,17 @@ impl<'a> Client<'a> { let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, token); - let resp = self.client.get(url).headers(headers).send().await?; + let resp = self + .client + .get(url) + .header(USER_AGENT, format!("atuin/{}", VERSION)) + .headers(headers) + .send() + .await?; + + if resp.status() != StatusCode::OK { + return Err(eyre!("failed to get count (are you logged in?)")); + } let count = resp.json::<CountResponse>().await?; @@ -66,6 +141,7 @@ impl<'a> Client<'a> { .client .get(url) .header(AUTHORIZATION, format!("Token {}", self.token)) + .header(USER_AGENT, format!("atuin/{}", VERSION)) .send() .await?; @@ -88,9 +164,33 @@ impl<'a> Client<'a> { .post(url) .json(history) .header(AUTHORIZATION, format!("Token {}", self.token)) + .header(USER_AGENT, format!("atuin/{}", VERSION)) .send() .await?; Ok(()) } + + pub async fn login(&self, username: &str, password: &str) -> Result<LoginResponse> { + let mut map = HashMap::new(); + map.insert("username", username); + map.insert("password", password); + + let url = format!("{}/login", self.sync_addr); + let resp = self + .client + .post(url) + .json(&map) + .header(USER_AGENT, format!("atuin/{}", VERSION)) + .send() + .await?; + + if resp.status() != reqwest::StatusCode::OK { + return Err(eyre!("invalid login details")); + } + + let session = resp.json::<LoginResponse>().await?; + + Ok(session) + } } |