From 2315962e18d31a35950e6d06e91d4e2a6ac9bfc9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 31 Jul 2025 22:50:38 -0400 Subject: [PATCH] cloud_api_client: Add `accept_terms_of_service` method (#35452) This PR adds an `accept_terms_of_service` method to the `CloudApiClient`. Release Notes: - N/A --- .../cloud_api_client/src/cloud_api_client.rs | 68 ++++++++++++++----- crates/cloud_api_types/src/cloud_api_types.rs | 5 ++ 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/crates/cloud_api_client/src/cloud_api_client.rs b/crates/cloud_api_client/src/cloud_api_client.rs index 5a768810c0f50ba2d513413808e9ba984fbd5518..6689475dae254abd5d9e7dd7faddefdc4fd2e7ab 100644 --- a/crates/cloud_api_client/src/cloud_api_client.rs +++ b/crates/cloud_api_client/src/cloud_api_client.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use anyhow::{Result, anyhow}; pub use cloud_api_types::*; use futures::AsyncReadExt as _; +use http_client::http::request; use http_client::{AsyncBody, HttpClientWithUrl, Method, Request}; use parking_lot::RwLock; @@ -51,17 +52,26 @@ impl CloudApiClient { )) } + fn build_request( + &self, + req: request::Builder, + body: impl Into, + ) -> Result> { + Ok(req + .header("Content-Type", "application/json") + .header("Authorization", self.authorization_header()?) + .body(body.into())?) + } + pub async fn get_authenticated_user(&self) -> Result { - let request = Request::builder() - .method(Method::GET) - .uri( + let request = self.build_request( + Request::builder().method(Method::GET).uri( self.http_client .build_zed_cloud_url("/client/users/me", &[])? .as_ref(), - ) - .header("Content-Type", "application/json") - .header("Authorization", self.authorization_header()?) - .body(AsyncBody::default())?; + ), + AsyncBody::default(), + )?; let mut response = self.http_client.send(request).await?; @@ -81,25 +91,49 @@ impl CloudApiClient { Ok(serde_json::from_str(&body)?) } + pub async fn accept_terms_of_service(&self) -> Result { + let request = self.build_request( + Request::builder().method(Method::POST).uri( + self.http_client + .build_zed_cloud_url("/client/terms_of_service/accept", &[])? + .as_ref(), + ), + AsyncBody::default(), + )?; + + let mut response = self.http_client.send(request).await?; + + if !response.status().is_success() { + let mut body = String::new(); + response.body_mut().read_to_string(&mut body).await?; + + anyhow::bail!( + "Failed to accept terms of service.\nStatus: {:?}\nBody: {body}", + response.status() + ) + } + + let mut body = String::new(); + response.body_mut().read_to_string(&mut body).await?; + + Ok(serde_json::from_str(&body)?) + } + pub async fn create_llm_token( &self, system_id: Option, ) -> Result { - let mut request_builder = Request::builder() - .method(Method::POST) - .uri( - self.http_client - .build_zed_cloud_url("/client/llm_tokens", &[])? - .as_ref(), - ) - .header("Content-Type", "application/json") - .header("Authorization", self.authorization_header()?); + let mut request_builder = Request::builder().method(Method::POST).uri( + self.http_client + .build_zed_cloud_url("/client/llm_tokens", &[])? + .as_ref(), + ); if let Some(system_id) = system_id { request_builder = request_builder.header(ZED_SYSTEM_ID_HEADER_NAME, system_id); } - let request = request_builder.body(AsyncBody::default())?; + let request = self.build_request(request_builder, AsyncBody::default())?; let mut response = self.http_client.send(request).await?; diff --git a/crates/cloud_api_types/src/cloud_api_types.rs b/crates/cloud_api_types/src/cloud_api_types.rs index e4d4a27af5bfaa7e83522aec5eed7ac1e895fbe0..b38b38cde1d5c7c34642329196d25781fea6355a 100644 --- a/crates/cloud_api_types/src/cloud_api_types.rs +++ b/crates/cloud_api_types/src/cloud_api_types.rs @@ -41,6 +41,11 @@ pub struct SubscriptionPeriod { pub ended_at: Timestamp, } +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct AcceptTermsOfServiceResponse { + pub user: AuthenticatedUser, +} + #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct LlmToken(pub String);