use crate::{anthropic_request_json, ApiResponseOrError, Credentials};
use derive_builder::Builder;
use reqwest::Method;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum UserRole {
User,
Developer,
Billing,
Admin,
}
#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct User {
pub id: String,
pub email: String,
pub name: String,
pub added_at: String,
pub role: UserRole,
#[serde(rename = "type")]
pub user_type: String,
}
#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct UserList {
pub data: Vec<User>,
pub first_id: Option<String>,
pub last_id: Option<String>,
pub has_more: bool,
}
#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct UserDeleted {
pub id: String,
#[serde(rename = "type")]
pub deleted_type: String,
}
#[derive(Serialize, Builder, Debug, Clone)]
#[builder(derive(Clone, Debug, PartialEq))]
#[builder(pattern = "owned")]
#[builder(name = "UserListBuilder")]
#[builder(setter(strip_option, into))]
pub struct UserListRequest {
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub before_id: Option<String>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub after_id: Option<String>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing)]
#[builder(default)]
pub credentials: Option<Credentials>,
}
#[derive(Serialize, Builder, Debug, Clone)]
#[builder(derive(Clone, Debug, PartialEq))]
#[builder(pattern = "owned")]
#[builder(name = "UserBuilder")]
#[builder(setter(strip_option, into))]
pub struct UserRequest {
pub user_id: String,
#[serde(skip_serializing)]
#[builder(default)]
pub credentials: Option<Credentials>,
}
#[derive(Serialize, Builder, Debug, Clone)]
#[builder(derive(Clone, Debug, PartialEq))]
#[builder(pattern = "owned")]
#[builder(name = "UserUpdateBuilder")]
#[builder(setter(strip_option, into))]
pub struct UserUpdateRequest {
#[serde(skip_serializing)]
pub user_id: String,
pub role: UserRole,
#[serde(skip_serializing)]
#[builder(default)]
pub credentials: Option<Credentials>,
}
#[derive(Serialize, Builder, Debug, Clone)]
#[builder(derive(Clone, Debug, PartialEq))]
#[builder(pattern = "owned")]
#[builder(name = "UserRemoveBuilder")]
#[builder(setter(strip_option, into))]
pub struct UserRemoveRequest {
pub user_id: String,
#[serde(skip_serializing)]
#[builder(default)]
pub credentials: Option<Credentials>,
}
impl UserList {
pub fn builder() -> UserListBuilder {
UserListBuilder::create_empty()
}
pub async fn create(request: UserListRequest) -> ApiResponseOrError<Self> {
let credentials_opt = request.credentials.clone();
let mut query_params = Vec::new();
if let Some(before_id) = &request.before_id {
query_params.push(("before_id", before_id.clone()));
}
if let Some(after_id) = &request.after_id {
query_params.push(("after_id", after_id.clone()));
}
if let Some(limit) = request.limit {
query_params.push(("limit", limit.to_string()));
}
if let Some(email) = &request.email {
query_params.push(("email", email.clone()));
}
anthropic_request_json(
Method::GET,
"organizations/users",
|r| r.query(&query_params),
credentials_opt,
)
.await
}
}
impl User {
pub fn builder(user_id: impl Into<String>) -> UserBuilder {
UserBuilder::create_empty().user_id(user_id)
}
pub async fn create(request: UserRequest) -> ApiResponseOrError<Self> {
let credentials_opt = request.credentials.clone();
let route = format!("organizations/users/{}", request.user_id);
anthropic_request_json(Method::GET, &route, |r| r, credentials_opt).await
}
pub fn update_builder(user_id: impl Into<String>) -> UserUpdateBuilder {
UserUpdateBuilder::create_empty().user_id(user_id)
}
pub async fn update(request: UserUpdateRequest) -> ApiResponseOrError<Self> {
let credentials_opt = request.credentials.clone();
let route = format!("organizations/users/{}", request.user_id);
anthropic_request_json(Method::POST, &route, |r| r.json(&request), credentials_opt).await
}
pub fn remove_builder(user_id: impl Into<String>) -> UserRemoveBuilder {
UserRemoveBuilder::create_empty().user_id(user_id)
}
pub async fn remove(request: UserRemoveRequest) -> ApiResponseOrError<UserDeleted> {
let credentials_opt = request.credentials.clone();
let route = format!("organizations/users/{}", request.user_id);
anthropic_request_json(Method::DELETE, &route, |r| r, credentials_opt).await
}
}
impl UserListBuilder {
pub async fn create(self) -> ApiResponseOrError<UserList> {
let request = self.build().unwrap();
UserList::create(request).await
}
}
impl UserBuilder {
pub async fn create(self) -> ApiResponseOrError<User> {
let request = self.build().unwrap();
User::create(request).await
}
}
impl UserUpdateBuilder {
pub async fn create(self) -> ApiResponseOrError<User> {
let request = self.build().unwrap();
User::update(request).await
}
}
impl UserRemoveBuilder {
pub async fn create(self) -> ApiResponseOrError<UserDeleted> {
let request = self.build().unwrap();
User::remove(request).await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Credentials;
#[tokio::test]
#[ignore] async fn test_list_users() {
let credentials = Credentials::from_env();
let users = UserList::builder()
.credentials(credentials)
.create()
.await
.unwrap();
assert!(users.data.len() > 0);
}
#[tokio::test]
#[ignore] async fn test_get_user() {
let credentials = Credentials::from_env();
let users = UserList::builder()
.credentials(credentials.clone())
.create()
.await
.unwrap();
if let Some(user) = users.data.first() {
let user_id = &user.id;
let user_details = User::builder(user_id)
.credentials(credentials)
.create()
.await
.unwrap();
assert_eq!(user_details.id, *user_id);
}
}
}