kanidmd_core/actors/
v1_scim.rs

1use super::{QueryServerReadV1, QueryServerWriteV1};
2use kanidm_proto::scim_v1::{
3    client::ScimFilter, server::ScimEntryKanidm, ScimEntryGetQuery, ScimSyncRequest, ScimSyncState,
4};
5use kanidmd_lib::idm::scim::{
6    GenerateScimSyncTokenEvent, ScimSyncFinaliseEvent, ScimSyncTerminateEvent, ScimSyncUpdateEvent,
7};
8use kanidmd_lib::idm::server::IdmServerTransaction;
9use kanidmd_lib::prelude::*;
10
11impl QueryServerWriteV1 {
12    #[instrument(
13        level = "info",
14        skip_all,
15        fields(uuid = ?eventid)
16    )]
17    pub async fn handle_sync_account_token_generate(
18        &self,
19        client_auth_info: ClientAuthInfo,
20        uuid_or_name: String,
21        label: String,
22        eventid: Uuid,
23    ) -> Result<String, OperationError> {
24        let ct = duration_from_epoch_now();
25        let mut idms_prox_write = self.idms.proxy_write(ct).await?;
26        let ident = idms_prox_write
27            .validate_client_auth_info_to_ident(client_auth_info, ct)
28            .map_err(|e| {
29                admin_error!(err = ?e, "Invalid identity");
30                e
31            })?;
32
33        let target = idms_prox_write
34            .qs_write
35            .name_to_uuid(uuid_or_name.as_str())
36            .map_err(|e| {
37                admin_error!(err = ?e, "Error resolving id to target");
38                e
39            })?;
40
41        let gte = GenerateScimSyncTokenEvent {
42            ident,
43            target,
44            label,
45        };
46
47        idms_prox_write
48            .scim_sync_generate_token(&gte, ct)
49            .map(|token| token.to_string())
50            .and_then(|r| idms_prox_write.commit().map(|_| r))
51    }
52
53    #[instrument(
54        level = "info",
55        skip_all,
56        fields(uuid = ?eventid)
57    )]
58    pub async fn handle_sync_account_token_destroy(
59        &self,
60        client_auth_info: ClientAuthInfo,
61        uuid_or_name: String,
62        eventid: Uuid,
63    ) -> Result<(), OperationError> {
64        let ct = duration_from_epoch_now();
65        let mut idms_prox_write = self.idms.proxy_write(ct).await?;
66        let ident = idms_prox_write
67            .validate_client_auth_info_to_ident(client_auth_info, ct)
68            .map_err(|e| {
69                admin_error!(err = ?e, "Invalid identity");
70                e
71            })?;
72
73        let target = idms_prox_write
74            .qs_write
75            .name_to_uuid(uuid_or_name.as_str())
76            .map_err(|e| {
77                admin_error!(err = ?e, "Error resolving id to target");
78                e
79            })?;
80
81        idms_prox_write
82            .sync_account_destroy_token(&ident, target, ct)
83            .and_then(|r| idms_prox_write.commit().map(|_| r))
84    }
85
86    #[instrument(
87        level = "info",
88        skip_all,
89        fields(uuid = ?eventid)
90    )]
91    pub async fn handle_sync_account_finalise(
92        &self,
93        client_auth_info: ClientAuthInfo,
94        uuid_or_name: String,
95        eventid: Uuid,
96    ) -> Result<(), OperationError> {
97        let ct = duration_from_epoch_now();
98        let mut idms_prox_write = self.idms.proxy_write(ct).await?;
99        let ident = idms_prox_write
100            .validate_client_auth_info_to_ident(client_auth_info, ct)
101            .map_err(|e| {
102                admin_error!(err = ?e, "Invalid identity");
103                e
104            })?;
105
106        let target = idms_prox_write
107            .qs_write
108            .name_to_uuid(uuid_or_name.as_str())
109            .map_err(|e| {
110                admin_error!(err = ?e, "Error resolving id to target");
111                e
112            })?;
113
114        let sfe = ScimSyncFinaliseEvent { ident, target };
115
116        idms_prox_write
117            .scim_sync_finalise(&sfe)
118            .and_then(|r| idms_prox_write.commit().map(|_| r))
119    }
120
121    #[instrument(
122        level = "info",
123        skip_all,
124        fields(uuid = ?eventid)
125    )]
126    pub async fn handle_sync_account_terminate(
127        &self,
128        client_auth_info: ClientAuthInfo,
129        uuid_or_name: String,
130        eventid: Uuid,
131    ) -> Result<(), OperationError> {
132        let ct = duration_from_epoch_now();
133        let mut idms_prox_write = self.idms.proxy_write(ct).await?;
134        let ident = idms_prox_write
135            .validate_client_auth_info_to_ident(client_auth_info, ct)
136            .map_err(|e| {
137                admin_error!(err = ?e, "Invalid identity");
138                e
139            })?;
140
141        let target = idms_prox_write
142            .qs_write
143            .name_to_uuid(uuid_or_name.as_str())
144            .map_err(|e| {
145                admin_error!(err = ?e, "Error resolving id to target");
146                e
147            })?;
148
149        let ste = ScimSyncTerminateEvent { ident, target };
150
151        idms_prox_write
152            .scim_sync_terminate(&ste)
153            .and_then(|r| idms_prox_write.commit().map(|_| r))
154    }
155
156    #[instrument(
157        level = "info",
158        skip_all,
159        fields(uuid = ?eventid)
160    )]
161    pub async fn handle_scim_sync_apply(
162        &self,
163        client_auth_info: ClientAuthInfo,
164        changes: ScimSyncRequest,
165        eventid: Uuid,
166    ) -> Result<(), OperationError> {
167        let ct = duration_from_epoch_now();
168        let mut idms_prox_write = self.idms.proxy_write(ct).await?;
169
170        let ident =
171            idms_prox_write.validate_sync_client_auth_info_to_ident(client_auth_info, ct)?;
172
173        let sse = ScimSyncUpdateEvent { ident };
174
175        idms_prox_write
176            .scim_sync_apply(&sse, &changes, ct)
177            .and_then(|r| idms_prox_write.commit().map(|_| r))
178    }
179}
180
181impl QueryServerReadV1 {
182    #[instrument(
183        level = "info",
184        skip_all,
185        fields(uuid = ?eventid)
186    )]
187    pub async fn handle_scim_sync_status(
188        &self,
189        client_auth_info: ClientAuthInfo,
190        eventid: Uuid,
191    ) -> Result<ScimSyncState, OperationError> {
192        let ct = duration_from_epoch_now();
193        let mut idms_prox_read = self.idms.proxy_read().await?;
194
195        let ident = idms_prox_read.validate_sync_client_auth_info_to_ident(client_auth_info, ct)?;
196
197        idms_prox_read.scim_sync_get_state(&ident)
198    }
199
200    #[instrument(
201        level = "info",
202        skip_all,
203        fields(uuid = ?eventid)
204    )]
205    pub async fn scim_entry_id_get(
206        &self,
207        client_auth_info: ClientAuthInfo,
208        eventid: Uuid,
209        uuid_or_name: String,
210        class: EntryClass,
211        query: ScimEntryGetQuery,
212    ) -> Result<ScimEntryKanidm, OperationError> {
213        let ct = duration_from_epoch_now();
214        let mut idms_prox_read = self.idms.proxy_read().await?;
215        let ident = idms_prox_read
216            .validate_client_auth_info_to_ident(client_auth_info, ct)
217            .inspect_err(|err| {
218                error!(?err, "Invalid identity");
219            })?;
220
221        let target_uuid = idms_prox_read
222            .qs_read
223            .name_to_uuid(uuid_or_name.as_str())
224            .inspect_err(|err| {
225                error!(?err, "Error resolving id to target");
226            })?;
227
228        idms_prox_read
229            .qs_read
230            .scim_entry_id_get_ext(target_uuid, class, query, ident)
231    }
232
233    #[instrument(
234        level = "info",
235        skip_all,
236        fields(uuid = ?eventid)
237    )]
238    pub async fn scim_entry_search(
239        &self,
240        client_auth_info: ClientAuthInfo,
241        eventid: Uuid,
242        filter: ScimFilter,
243        query: ScimEntryGetQuery,
244    ) -> Result<Vec<ScimEntryKanidm>, OperationError> {
245        let ct = duration_from_epoch_now();
246        let mut idms_prox_read = self.idms.proxy_read().await?;
247        let ident = idms_prox_read
248            .validate_client_auth_info_to_ident(client_auth_info, ct)
249            .inspect_err(|err| {
250                error!(?err, "Invalid identity");
251            })?;
252
253        idms_prox_read.qs_read.scim_search_ext(ident, filter, query)
254    }
255}