use reqwest::Method;
use serde::de::{self, Deserializer};
use serde::{Deserialize, Serialize};
use crate::client::Client;
use crate::error::BoxxkiteError;
use crate::sandboxes::UsageSummary;
#[derive(Debug, Clone, Deserialize)]
pub struct Account {
pub id: String,
pub email: String,
pub created_at: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MessageResponse {
pub message: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TokenPair {
pub access_token: String,
pub token_type: String,
pub expires_in: i64,
pub refresh_token: Option<String>,
pub account: Account,
}
#[derive(Debug, Clone, Serialize)]
pub struct AllowedCommandRule {
pub command: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub args_allow: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub args_deny: Vec<String>,
}
impl AllowedCommandRule {
pub fn new(command: impl Into<String>) -> Self {
Self {
command: command.into(),
args_allow: Vec::new(),
args_deny: Vec::new(),
}
}
pub fn args_allow<I, S>(mut self, patterns: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.args_allow = patterns.into_iter().map(Into::into).collect();
self
}
pub fn args_deny<I, S>(mut self, patterns: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.args_deny = patterns.into_iter().map(Into::into).collect();
self
}
}
impl<'de> Deserialize<'de> for AllowedCommandRule {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum Raw {
Bare(String),
Full {
command: String,
#[serde(default)]
args_allow: Vec<String>,
#[serde(default)]
args_deny: Vec<String>,
},
}
match Raw::deserialize(deserializer).map_err(de::Error::custom)? {
Raw::Bare(command) => Ok(Self::new(command)),
Raw::Full {
command,
args_allow,
args_deny,
} => Ok(Self {
command,
args_allow,
args_deny,
}),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct AllowedCommandsResponse {
#[serde(default)]
pub rules: Vec<AllowedCommandRule>,
}
impl Client {
pub async fn account(&self) -> Result<Account, BoxxkiteError> {
let builder = self.request(Method::GET, "/v1/account");
self.send(builder).await
}
pub async fn usage(&self) -> Result<UsageSummary, BoxxkiteError> {
let builder = self.request(Method::GET, "/v1/usage");
self.send(builder).await
}
pub async fn request_password_reset(
&self,
email: &str,
) -> Result<MessageResponse, BoxxkiteError> {
#[derive(Serialize)]
struct Body<'a> {
email: &'a str,
}
let builder = self
.request(Method::POST, "/v1/auth/password-reset/request")
.json(&Body { email });
self.send(builder).await
}
pub async fn confirm_password_reset(
&self,
token: &str,
new_password: &str,
) -> Result<MessageResponse, BoxxkiteError> {
#[derive(Serialize)]
struct Body<'a> {
token: &'a str,
new_password: &'a str,
}
let builder = self
.request(Method::POST, "/v1/auth/password-reset/confirm")
.json(&Body {
token,
new_password,
});
self.send(builder).await
}
pub async fn verify_email(&self, token: &str) -> Result<MessageResponse, BoxxkiteError> {
#[derive(Serialize)]
struct Body<'a> {
token: &'a str,
}
let builder = self
.request(Method::POST, "/v1/auth/verify-email")
.json(&Body { token });
self.send(builder).await
}
pub async fn resend_verification(
&self,
access_token: &str,
) -> Result<MessageResponse, BoxxkiteError> {
let builder =
self.request_with_auth(Method::POST, "/v1/auth/resend-verification", access_token);
self.send(builder).await
}
pub async fn refresh_token(&self, refresh_token: &str) -> Result<TokenPair, BoxxkiteError> {
#[derive(Serialize)]
struct Body<'a> {
refresh_token: &'a str,
}
let builder = self
.request(Method::POST, "/v1/auth/refresh")
.json(&Body { refresh_token });
self.send(builder).await
}
pub async fn logout(&self, refresh_token: &str) -> Result<(), BoxxkiteError> {
#[derive(Serialize)]
struct Body<'a> {
refresh_token: &'a str,
}
let builder = self
.request(Method::POST, "/v1/auth/logout")
.json(&Body { refresh_token });
self.send_no_content(builder).await
}
pub async fn get_allowed_commands(&self) -> Result<AllowedCommandsResponse, BoxxkiteError> {
let builder = self.request(Method::GET, "/v1/account/allowed-commands");
self.send(builder).await
}
pub async fn set_allowed_commands(
&self,
rules: Vec<AllowedCommandRule>,
) -> Result<AllowedCommandsResponse, BoxxkiteError> {
let body = AllowedCommandsResponse { rules };
let builder = self
.request(Method::PUT, "/v1/account/allowed-commands")
.json(&body);
self.send(builder).await
}
pub async fn clear_allowed_commands(&self) -> Result<(), BoxxkiteError> {
let builder = self.request(Method::DELETE, "/v1/account/allowed-commands");
self.send_no_content(builder).await
}
}