cx_sdk/client/
users.rs

1// Copyright 2024 Coralogix Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use serde::{
15    Deserialize,
16    Serialize,
17};
18
19use crate::{
20    CoralogixRegion,
21    RUSTC_VERSION,
22    SDK_CORRELATION_ID_HEADER_NAME,
23    SDK_LANGUAGE_HEADER_NAME,
24    SDK_RUSTC_VERSION_HEADER_NAME,
25    SDK_VERSION,
26    SDK_VERSION_HEADER_NAME,
27    auth::{
28        ApiKey,
29        AuthContext,
30    },
31};
32
33#[derive(Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35/// A SCIM User.
36pub struct ScimUser {
37    /// The schemas of the SCIM user.
38    pub schemas: Vec<String>,
39    /// The ID of the SCIM user.
40    pub id: Option<String>,
41    /// The name of the SCIM user.
42    pub user_name: String,
43    /// Whether the SCIM user is active.
44    pub active: bool,
45    /// The name of the SCIM user.
46    pub name: ScimUserName,
47    /// The emails of the SCIM user.
48    pub emails: Vec<ScimUserEmail>,
49    /// The groups of the SCIM user.
50    pub groups: Vec<ScimUserGroup>,
51}
52
53#[derive(Serialize, Deserialize)]
54#[serde(rename_all = "camelCase")]
55/// The name of a SCIM user.
56pub struct ScimUserName {
57    /// The given name of the SCIM user.
58    pub given_name: String,
59    /// The family name of the SCIM user.
60    pub family_name: String,
61}
62
63#[derive(Serialize, Deserialize)]
64#[serde(rename_all = "camelCase")]
65/// The email of a SCIM user.
66pub struct ScimUserEmail {
67    /// The email address of the SCIM user.
68    pub value: String,
69    /// The type of the email address.
70    pub r#type: Option<String>,
71    /// Whether the email address is primary.
72    pub primary: bool,
73}
74
75#[derive(Serialize, Deserialize)]
76#[serde(rename_all = "camelCase")]
77/// The phone number of a SCIM user.
78pub struct ScimUserGroup {
79    /// The value of the SCIM user group.
80    pub value: String,
81}
82
83/// ListResponse represents the structure of the response for the List SCIM Users operation.
84#[derive(Serialize, Deserialize)]
85#[serde(rename_all = "camelCase")]
86pub struct ListResponse {
87    /// The schemas of the SCIM users.
88    pub schemas: Vec<String>,
89    /// The total number of results.
90    pub total_results: usize,
91    /// The list of SCIM users.
92    #[serde(rename = "Resources")]
93    pub resources: Vec<ScimUser>,
94}
95
96/// UsersClient is a client for the users API.
97pub struct UsersClient {
98    target_url: String,
99    http_client: reqwest::Client,
100    api_key: ApiKey,
101    correlation_id: String,
102}
103
104impl UsersClient {
105    /// Create a new UsersClient.
106    ///
107    /// # Arguments
108    /// * `region` - The [`CoralogixRegion`] to connect to.
109    /// * `auth_context` - Th [`AuthContext`] to use for authentication.
110    pub fn new(region: CoralogixRegion, auth_context: AuthContext) -> Self {
111        Self {
112            http_client: reqwest::Client::new(),
113            api_key: auth_context.team_level_api_key,
114            target_url: region.rest_endpoint() + "/scim/Users",
115            correlation_id: uuid::Uuid::new_v4().to_string(),
116        }
117    }
118
119    /// Create a [`ScimUser`].
120    pub async fn create(&self, user: ScimUser) -> Result<ScimUser, reqwest::Error> {
121        let response = self
122            .http_client
123            .post(&self.target_url)
124            .header("Authorization", format!("Bearer {}", self.api_key.token()))
125            .header(SDK_VERSION_HEADER_NAME, SDK_VERSION)
126            .header(SDK_LANGUAGE_HEADER_NAME, "rust")
127            .header(SDK_RUSTC_VERSION_HEADER_NAME, RUSTC_VERSION)
128            .header(SDK_CORRELATION_ID_HEADER_NAME, &self.correlation_id)
129            .json(&user)
130            .send()
131            .await?;
132        response.json().await
133    }
134
135    /// Get a SCIM user by ID.
136    ///
137    /// # Arguments
138    /// * `id` - The ID of the SCIM user.
139    pub async fn get(&self, id: &str) -> Result<ScimUser, reqwest::Error> {
140        let url = format!("{}/{}", self.target_url, id);
141        let response = self
142            .http_client
143            .get(&url)
144            .header("Authorization", format!("Bearer {}", self.api_key.token()))
145            .header(SDK_VERSION_HEADER_NAME, SDK_VERSION)
146            .header(SDK_LANGUAGE_HEADER_NAME, "rust")
147            .header(SDK_RUSTC_VERSION_HEADER_NAME, RUSTC_VERSION)
148            .header(SDK_CORRELATION_ID_HEADER_NAME, &self.correlation_id)
149            .send()
150            .await?;
151        response.json().await
152    }
153
154    /// Update a SCIM user.
155    ///
156    /// # Arguments
157    /// * `user` - The [`ScimUser`] to update.
158    pub async fn update(&self, user: ScimUser) -> Result<ScimUser, reqwest::Error> {
159        let url = format!("{}/{}", self.target_url, user.id.as_ref().unwrap());
160        let response = self
161            .http_client
162            .put(&url)
163            .header("Authorization", format!("Bearer {}", self.api_key.token()))
164            .header(SDK_VERSION_HEADER_NAME, SDK_VERSION)
165            .header(SDK_LANGUAGE_HEADER_NAME, "rust")
166            .header(SDK_RUSTC_VERSION_HEADER_NAME, RUSTC_VERSION)
167            .header(SDK_CORRELATION_ID_HEADER_NAME, &self.correlation_id)
168            .json(&user)
169            .send()
170            .await?;
171        response.json().await
172    }
173
174    /// Delete a SCIM user by ID.
175    ///
176    /// # Arguments
177    /// * `id` - The ID of the SCIM user.
178    pub async fn delete(&self, id: &str) -> Result<(), reqwest::Error> {
179        let url = format!("{}/{}", self.target_url, id);
180        let response = self
181            .http_client
182            .delete(&url)
183            .header("Authorization", format!("Bearer {}", self.api_key.token()))
184            .header(SDK_VERSION_HEADER_NAME, SDK_VERSION)
185            .header(SDK_LANGUAGE_HEADER_NAME, "rust")
186            .header(SDK_RUSTC_VERSION_HEADER_NAME, RUSTC_VERSION)
187            .header(SDK_CORRELATION_ID_HEADER_NAME, &self.correlation_id)
188            .send()
189            .await?;
190        response.error_for_status()?;
191        Ok(())
192    }
193
194    /// List all SCIM users.
195    ///
196    /// This function retrieves all SCIM users.
197    pub async fn list(&self) -> Result<Vec<ScimUser>, reqwest::Error> {
198        let response = self
199            .http_client
200            .get(&self.target_url)
201            .header("Authorization", format!("Bearer {}", self.api_key.token()))
202            .header(SDK_VERSION_HEADER_NAME, SDK_VERSION)
203            .header(SDK_LANGUAGE_HEADER_NAME, "rust")
204            .header(SDK_RUSTC_VERSION_HEADER_NAME, RUSTC_VERSION)
205            .header(SDK_CORRELATION_ID_HEADER_NAME, &self.correlation_id)
206            .send()
207            .await?;
208
209        let list_response: ListResponse = response.json().await?;
210        Ok(list_response.resources)
211    }
212}