scim_server/operation_handler/builders/
request.rs

1//! Request builder utilities for ScimOperationRequest
2//!
3//! This module provides convenient builder methods for constructing
4//! ScimOperationRequest instances for different operation types.
5
6use crate::{
7    operation_handler::core::{ScimOperationRequest, ScimOperationType, ScimQuery},
8    resource::{TenantContext, version::ScimVersion},
9};
10use serde_json::Value;
11
12impl ScimOperationRequest {
13    /// Create a new create operation request.
14    pub fn create(resource_type: impl Into<String>, data: Value) -> Self {
15        Self {
16            operation: ScimOperationType::Create,
17            resource_type: resource_type.into(),
18            resource_id: None,
19            data: Some(data),
20            query: None,
21            tenant_context: None,
22            request_id: None,
23            expected_version: None,
24        }
25    }
26
27    /// Create a new get operation request.
28    pub fn get(resource_type: impl Into<String>, resource_id: impl Into<String>) -> Self {
29        Self {
30            operation: ScimOperationType::Get,
31            resource_type: resource_type.into(),
32            resource_id: Some(resource_id.into()),
33            data: None,
34            query: None,
35            tenant_context: None,
36            request_id: None,
37            expected_version: None,
38        }
39    }
40
41    /// Create a new update operation request.
42    pub fn update(
43        resource_type: impl Into<String>,
44        resource_id: impl Into<String>,
45        data: Value,
46    ) -> Self {
47        Self {
48            operation: ScimOperationType::Update,
49            resource_type: resource_type.into(),
50            resource_id: Some(resource_id.into()),
51            data: Some(data),
52            query: None,
53            tenant_context: None,
54            request_id: None,
55            expected_version: None,
56        }
57    }
58
59    /// Create a new delete operation request.
60    pub fn delete(resource_type: impl Into<String>, resource_id: impl Into<String>) -> Self {
61        Self {
62            operation: ScimOperationType::Delete,
63            resource_type: resource_type.into(),
64            resource_id: Some(resource_id.into()),
65            data: None,
66            query: None,
67            tenant_context: None,
68            request_id: None,
69            expected_version: None,
70        }
71    }
72
73    /// Create a new list operation request.
74    pub fn list(resource_type: impl Into<String>) -> Self {
75        Self {
76            operation: ScimOperationType::List,
77            resource_type: resource_type.into(),
78            resource_id: None,
79            data: None,
80            query: None,
81            tenant_context: None,
82            request_id: None,
83            expected_version: None,
84        }
85    }
86
87    /// Create a new search operation request.
88    pub fn search(
89        resource_type: impl Into<String>,
90        attribute: impl Into<String>,
91        value: Value,
92    ) -> Self {
93        Self {
94            operation: ScimOperationType::Search,
95            resource_type: resource_type.into(),
96            resource_id: None,
97            data: None,
98            query: Some(ScimQuery {
99                count: None,
100                start_index: None,
101                filter: None,
102                attributes: None,
103                excluded_attributes: None,
104                search_attribute: Some(attribute.into()),
105                search_value: Some(value),
106            }),
107            tenant_context: None,
108            request_id: None,
109            expected_version: None,
110        }
111    }
112
113    /// Create a new get schemas operation request.
114    pub fn get_schemas() -> Self {
115        Self {
116            operation: ScimOperationType::GetSchemas,
117            resource_type: "Schema".to_string(),
118            resource_id: None,
119            data: None,
120            query: None,
121            tenant_context: None,
122            request_id: None,
123            expected_version: None,
124        }
125    }
126
127    /// Create a new get schema operation request.
128    pub fn get_schema(schema_id: impl Into<String>) -> Self {
129        Self {
130            operation: ScimOperationType::GetSchema,
131            resource_type: "Schema".to_string(),
132            resource_id: Some(schema_id.into()),
133            data: None,
134            query: None,
135            tenant_context: None,
136            request_id: None,
137            expected_version: None,
138        }
139    }
140
141    /// Create a new resource exists operation request.
142    pub fn exists(resource_type: impl Into<String>, resource_id: impl Into<String>) -> Self {
143        Self {
144            operation: ScimOperationType::Exists,
145            resource_type: resource_type.into(),
146            resource_id: Some(resource_id.into()),
147            data: None,
148            query: None,
149            tenant_context: None,
150            request_id: None,
151            expected_version: None,
152        }
153    }
154
155    /// Add tenant context to the request.
156    pub fn with_tenant(mut self, tenant_context: TenantContext) -> Self {
157        self.tenant_context = Some(tenant_context);
158        self
159    }
160
161    /// Add request ID to the request.
162    pub fn with_request_id(mut self, request_id: impl Into<String>) -> Self {
163        self.request_id = Some(request_id.into());
164        self
165    }
166
167    /// Add query parameters to the request.
168    pub fn with_query(mut self, query: ScimQuery) -> Self {
169        self.query = Some(query);
170        self
171    }
172
173    /// Add expected version for conditional operations.
174    ///
175    /// This enables ETag-based concurrency control for update and delete operations.
176    /// The operation will only succeed if the current resource version matches
177    /// the expected version.
178    ///
179    /// # Examples
180    /// ```rust
181    /// use scim_server::operation_handler::ScimOperationRequest;
182    /// use scim_server::resource::version::ScimVersion;
183    /// use serde_json::json;
184    ///
185    /// let version = ScimVersion::parse_http_header("\"abc123\"").unwrap();
186    /// let request = ScimOperationRequest::update(
187    ///     "User",
188    ///     "123",
189    ///     json!({"userName": "updated.name"})
190    /// ).with_expected_version(version);
191    /// ```
192    pub fn with_expected_version(mut self, version: ScimVersion) -> Self {
193        self.expected_version = Some(version);
194        self
195    }
196}