infisical_api/api/
api.rs

1use async_trait::async_trait;
2use serde::de::{Deserialize, DeserializeOwned};
3
4use crate::api::models;
5use crate::error::{self, api, Result};
6
7use super::models::ApiResponse;
8
9/// Trait to extend the json deserialization functionality of [reqwest::Response]
10///
11/// The Infiscal API returns 200 by default, even if there were errors with the request.
12/// They instead include a JSON response with an error message and the true HTTP status code
13/// This trait calls [reqwest::Response.json] internally and converts the Infisical error response
14/// to an [infisical_rs::Error]
15#[async_trait]
16trait JsonProcessorExt {
17    async fn infisical_json<T>(self) -> Result<T>
18    where
19        T: DeserializeOwned;
20}
21
22#[async_trait]
23impl JsonProcessorExt for reqwest::Response {
24    async fn infisical_json<T>(self) -> Result<T>
25    where
26        T: DeserializeOwned,
27    {
28        match self.json::<ApiResponse<T>>().await? {
29            ApiResponse::Ok(res) => Ok(res),
30            ApiResponse::Err(err) => Err(error::api(err)),
31        }
32    }
33}
34
35pub async fn get_my_user(
36    client: &reqwest::Client,
37    request: models::GetMyUserRequest,
38) -> Result<models::GetMyUserResponse> {
39    let endpoint = format!("{}/v2/users/me", request.base_url);
40    Ok(client
41        .get(endpoint)
42        .send()
43        .await?
44        .infisical_json::<models::GetMyUserResponse>()
45        .await?)
46}
47
48pub async fn get_my_organizations(
49    client: &reqwest::Client,
50    request: models::GetMyOrganizationsRequest,
51) -> Result<models::GetOrganizationsResponse> {
52    let endpoint = format!("{}/v2/users/me/organizations", request.base_url);
53    Ok(client
54        .get(endpoint)
55        .send()
56        .await?
57        .infisical_json::<models::GetOrganizationsResponse>()
58        .await?)
59}
60
61pub async fn get_organization_memberships(
62    client: &reqwest::Client,
63    request: models::GetOrganizationMembershipsRequest,
64) -> Result<models::GetOrganizationMembershipsResponse> {
65    let endpoint = format!(
66        "{}/v2/organizations/{}/memberships",
67        request.base_url, request.organization_id
68    );
69
70    let res = client.get(&endpoint).send().await?;
71    println!("{}", res.text().await?);
72
73    Ok(client
74        .get(endpoint)
75        .send()
76        .await?
77        .infisical_json::<models::GetOrganizationMembershipsResponse>()
78        .await?)
79}
80
81pub async fn update_organization_membership(
82    client: &reqwest::Client,
83    request: models::UpdateOrganizationMembershipRequest,
84) -> Result<models::UpdateOrganizationMembershipResponse> {
85    let endpoint = format!(
86        "{}/v2/organizations/{}/memberships/{}",
87        request.base_url, request.organization_id, request.membership_id
88    );
89    Ok(client
90        .patch(endpoint)
91        .body(request.role)
92        .send()
93        .await?
94        .infisical_json::<models::UpdateOrganizationMembershipResponse>()
95        .await?)
96}
97
98pub async fn delete_organization_membership(
99    client: &reqwest::Client,
100    request: models::DeleteOrganizationMembershipRequest,
101) -> Result<models::UpdateOrganizationMembershipResponse> {
102    let endpoint = format!(
103        "{}/v2/organizations/{}/memberships/{}",
104        request.base_url, request.organization_id, request.membership_id
105    );
106    Ok(client
107        .delete(endpoint)
108        .send()
109        .await?
110        .infisical_json::<models::UpdateOrganizationMembershipResponse>()
111        .await?)
112}
113
114pub async fn get_organization_projects(
115    client: &reqwest::Client,
116    request: models::GetProjectsRequest,
117) -> Result<models::GetProjectsResponse> {
118    let endpoint = format!(
119        "{}/v2/organizations/{}/workspaces",
120        request.base_url, request.organization_id
121    );
122
123    Ok(client
124        .get(endpoint)
125        .send()
126        .await?
127        .infisical_json::<models::GetProjectsResponse>()
128        .await?)
129}
130
131pub async fn get_project_memberships(
132    client: &reqwest::Client,
133    request: models::GetProjectMembershipsRequest,
134) -> Result<models::GetProjectMembershipsResponse> {
135    let endpoint = format!(
136        "{}/v2/workspace/{}/memberships",
137        request.base_url, request.workspace_id
138    );
139    Ok(client
140        .get(endpoint)
141        .send()
142        .await?
143        .infisical_json::<models::GetProjectMembershipsResponse>()
144        .await?)
145}
146
147pub async fn update_project_membership(
148    client: &reqwest::Client,
149    request: models::UpdateProjectMembershipRequest,
150) -> Result<models::UpdateProjectMembershipResponse> {
151    let endpoint = format!(
152        "{}/v2/workspace/{}/memberships/{}",
153        request.base_url, request.workspace_id, request.membership_id
154    );
155    Ok(client
156        .patch(endpoint)
157        .body(request.role)
158        .send()
159        .await?
160        .infisical_json::<models::UpdateProjectMembershipResponse>()
161        .await?)
162}
163
164pub async fn delete_project_membership(
165    client: &reqwest::Client,
166    request: models::DeleteProjectMembershipRequest,
167) -> Result<models::DeleteProjectMembershipResponse> {
168    let endpoint = format!(
169        "{}/v2/workspace/{}/memberships/{}",
170        request.base_url, request.workspace_id, request.membership_id
171    );
172    Ok(client
173        .delete(endpoint)
174        .send()
175        .await?
176        .infisical_json::<models::DeleteProjectMembershipResponse>()
177        .await?)
178}
179
180pub async fn get_project_key(
181    client: &reqwest::Client,
182    request: models::GetProjectKeyRequest,
183) -> Result<models::GetProjectKeyResponse> {
184    let endpoint = format!(
185        "{}/v2/workspace/{}/encrypted-key",
186        request.base_url, request.workspace_id
187    );
188    Ok(client
189        .get(endpoint)
190        .send()
191        .await?
192        .infisical_json::<models::GetProjectKeyResponse>()
193        .await?)
194}
195
196pub async fn get_project_logs(
197    client: &reqwest::Client,
198    request: models::GetProjectLogsRequest,
199) -> Result<models::GetProjectLogsResponse> {
200    let endpoint = format!(
201        "{}/v1/workspace/{}/logs",
202        request.base_url, request.workspace_id
203    );
204    Ok(client
205        .get(endpoint)
206        .send()
207        .await?
208        .infisical_json::<models::GetProjectLogsResponse>()
209        .await?)
210}
211
212pub async fn get_project_snapshots(
213    client: &reqwest::Client,
214    request: models::GetProjectSnapshotsRequest,
215) -> Result<models::GetProjectSnapshotsResponse> {
216    let endpoint = format!(
217        "{}/v1/workspace/{}/secret-snapshots",
218        request.base_url, request.workspace_id
219    );
220
221    Ok(client
222        .get(endpoint)
223        .query(&request)
224        .send()
225        .await?
226        .infisical_json::<models::GetProjectSnapshotsResponse>()
227        .await?)
228}
229
230pub async fn roll_back_to_snapshot(
231    client: &reqwest::Client,
232    request: models::RollbackProjectToSnapshotRequest,
233) -> Result<models::RollbackProjectToSnapshotResponse> {
234    let endpoint = format!(
235        "{}/v1/workspace/{}/secret-snapshots/rollback",
236        request.base_url, request.workspace_id
237    );
238    Ok(client
239        .post(endpoint)
240        .body(request.version.to_string())
241        .send()
242        .await?
243        .infisical_json::<models::RollbackProjectToSnapshotResponse>()
244        .await?)
245}
246
247pub async fn create_project_secrets(
248    client: &reqwest::Client,
249    request: models::CreateProjectSecretsRequest,
250) -> Result<models::CreateProjectSecretsResponse> {
251    let endpoint = format!("{}/v2/secrets", request.base_url);
252
253    Ok(client
254        .post(endpoint)
255        .json(&request)
256        .send()
257        .await?
258        .infisical_json::<models::CreateProjectSecretsResponse>()
259        .await?)
260}
261
262/// Gets all of the secrets belonging the workspace provided in the request
263pub async fn get_project_secrets(
264    client: &reqwest::Client,
265    request: models::GetProjectSecretsRequest,
266) -> Result<models::GetProjectSecretsResponse> {
267    let endpoint = format!("{}/v2/secrets", request.base_url);
268
269    Ok(client
270        .get(endpoint)
271        .query(&request)
272        .send()
273        .await?
274        .infisical_json::<models::GetProjectSecretsResponse>()
275        .await?)
276}
277
278// This endpoint seems to be broken at the moment.
279// get a bad request response
280pub async fn get_service_tokens(
281    client: &reqwest::Client,
282    request: models::GetServiceTokensRequest,
283) -> Result<models::GetServiceTokensResponse> {
284    let endpoint = format!("{}/v2/service-token", request.base_url);
285
286    Ok(client
287        .get(endpoint)
288        .send()
289        .await?
290        .infisical_json::<models::GetServiceTokensResponse>()
291        .await?)
292}