scim2-client 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
scim2_client/client.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import json.decoder
|
|
3
|
+
from typing import Dict
|
|
3
4
|
from typing import List
|
|
4
5
|
from typing import Optional
|
|
5
6
|
from typing import Tuple
|
|
@@ -29,6 +30,71 @@ BASE_HEADERS = {
|
|
|
29
30
|
class SCIMClient:
|
|
30
31
|
"""An object that perform SCIM requests and validate responses."""
|
|
31
32
|
|
|
33
|
+
CREATION_RESPONSE_STATUS_CODES: List[int] = [
|
|
34
|
+
201,
|
|
35
|
+
409,
|
|
36
|
+
307,
|
|
37
|
+
308,
|
|
38
|
+
400,
|
|
39
|
+
401,
|
|
40
|
+
403,
|
|
41
|
+
404,
|
|
42
|
+
500,
|
|
43
|
+
]
|
|
44
|
+
"""Resource creation HTTP codes defined at :rfc:`RFC7644 §3.3
|
|
45
|
+
<7644#section-3.3>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
|
|
46
|
+
|
|
47
|
+
QUERY_RESPONSE_STATUS_CODES: List[int] = [200, 400, 307, 308, 401, 403, 404, 500]
|
|
48
|
+
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.2
|
|
49
|
+
<7644#section-3.4.2>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
|
|
50
|
+
|
|
51
|
+
SEARCH_RESPONSE_STATUS_CODES: List[int] = [
|
|
52
|
+
200,
|
|
53
|
+
307,
|
|
54
|
+
308,
|
|
55
|
+
400,
|
|
56
|
+
401,
|
|
57
|
+
403,
|
|
58
|
+
404,
|
|
59
|
+
409,
|
|
60
|
+
413,
|
|
61
|
+
500,
|
|
62
|
+
501,
|
|
63
|
+
]
|
|
64
|
+
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.3
|
|
65
|
+
<7644#section-3.4.3>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
|
|
66
|
+
|
|
67
|
+
DELETION_RESPONSE_STATUS_CODES: List[int] = [
|
|
68
|
+
204,
|
|
69
|
+
307,
|
|
70
|
+
308,
|
|
71
|
+
400,
|
|
72
|
+
401,
|
|
73
|
+
403,
|
|
74
|
+
404,
|
|
75
|
+
412,
|
|
76
|
+
500,
|
|
77
|
+
501,
|
|
78
|
+
]
|
|
79
|
+
"""Resource deletion HTTP codes defined at :rfc:`RFC7644 §3.6
|
|
80
|
+
<7644#section-3.6>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
|
|
81
|
+
|
|
82
|
+
REPLACEMENT_RESPONSE_STATUS_CODES: List[int] = [
|
|
83
|
+
200,
|
|
84
|
+
307,
|
|
85
|
+
308,
|
|
86
|
+
400,
|
|
87
|
+
401,
|
|
88
|
+
403,
|
|
89
|
+
404,
|
|
90
|
+
409,
|
|
91
|
+
412,
|
|
92
|
+
500,
|
|
93
|
+
501,
|
|
94
|
+
]
|
|
95
|
+
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.2
|
|
96
|
+
<7644#section-3.4.2>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
|
|
97
|
+
|
|
32
98
|
def __init__(self, client: Client, resource_types: Optional[Tuple[Type]] = None):
|
|
33
99
|
self.client = client
|
|
34
100
|
self.resource_types = resource_types or ()
|
|
@@ -47,7 +113,7 @@ class SCIMClient:
|
|
|
47
113
|
expected_type: Optional[Type] = None,
|
|
48
114
|
scim_ctx: Optional[Context] = None,
|
|
49
115
|
):
|
|
50
|
-
if response.status_code not in expected_status_codes:
|
|
116
|
+
if expected_status_codes and response.status_code not in expected_status_codes:
|
|
51
117
|
raise UnexpectedStatusCode(response)
|
|
52
118
|
|
|
53
119
|
# Interoperability considerations: The "application/scim+json" media
|
|
@@ -64,7 +130,8 @@ class SCIMClient:
|
|
|
64
130
|
# the errors in the body of the response in a JSON format
|
|
65
131
|
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.12
|
|
66
132
|
|
|
67
|
-
|
|
133
|
+
no_content_status_codes = [204, 205]
|
|
134
|
+
if response.status_code in no_content_status_codes:
|
|
68
135
|
response_payload = None
|
|
69
136
|
|
|
70
137
|
else:
|
|
@@ -79,15 +146,31 @@ class SCIMClient:
|
|
|
79
146
|
pass
|
|
80
147
|
|
|
81
148
|
if expected_type:
|
|
82
|
-
|
|
149
|
+
try:
|
|
150
|
+
return expected_type.model_validate(response_payload, scim_ctx=scim_ctx)
|
|
151
|
+
except ValidationError as exc:
|
|
152
|
+
exc.response_payload = response_payload
|
|
153
|
+
raise exc
|
|
83
154
|
|
|
84
155
|
return response_payload
|
|
85
156
|
|
|
86
|
-
def create(
|
|
157
|
+
def create(
|
|
158
|
+
self,
|
|
159
|
+
resource: Union[AnyResource, Dict],
|
|
160
|
+
check_request_payload: bool = True,
|
|
161
|
+
check_response_payload: bool = True,
|
|
162
|
+
check_status_code: bool = True,
|
|
163
|
+
**kwargs,
|
|
164
|
+
) -> Union[AnyResource, Error, Dict]:
|
|
87
165
|
"""Perform a POST request to create, as defined in :rfc:`RFC7644 §3.3
|
|
88
166
|
<7644#section-3.3>`.
|
|
89
167
|
|
|
90
168
|
:param resource: The resource to create
|
|
169
|
+
:param check_request_payload: If :data:`False`,
|
|
170
|
+
:code:`resource` is expected to be a dict that will be passed as-is in the request.
|
|
171
|
+
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
172
|
+
If set, the raw payload will be returned.
|
|
173
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
91
174
|
:param kwargs: Additional parameters passed to the underlying HTTP request
|
|
92
175
|
library.
|
|
93
176
|
|
|
@@ -96,30 +179,23 @@ class SCIMClient:
|
|
|
96
179
|
- The created object as returned by the server in case of success.
|
|
97
180
|
"""
|
|
98
181
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.12
|
|
111
|
-
307,
|
|
112
|
-
308,
|
|
113
|
-
400,
|
|
114
|
-
401,
|
|
115
|
-
403,
|
|
116
|
-
404,
|
|
117
|
-
500,
|
|
118
|
-
]
|
|
182
|
+
if not check_request_payload:
|
|
183
|
+
payload = resource
|
|
184
|
+
url = kwargs.pop("url", None)
|
|
185
|
+
|
|
186
|
+
else:
|
|
187
|
+
self.check_resource_type(resource.__class__)
|
|
188
|
+
url = kwargs.pop("url", self.resource_endpoint(resource.__class__))
|
|
189
|
+
payload = resource.model_dump(scim_ctx=Context.RESOURCE_CREATION_REQUEST)
|
|
190
|
+
|
|
191
|
+
response = self.client.post(url, json=payload, **kwargs)
|
|
192
|
+
|
|
119
193
|
return self.check_response(
|
|
120
194
|
response,
|
|
121
|
-
|
|
122
|
-
resource.__class__
|
|
195
|
+
self.CREATION_RESPONSE_STATUS_CODES if check_status_code else None,
|
|
196
|
+
resource.__class__
|
|
197
|
+
if check_request_payload and check_response_payload
|
|
198
|
+
else None,
|
|
123
199
|
scim_ctx=Context.RESOURCE_CREATION_RESPONSE,
|
|
124
200
|
)
|
|
125
201
|
|
|
@@ -127,9 +203,12 @@ class SCIMClient:
|
|
|
127
203
|
self,
|
|
128
204
|
resource_type: Type,
|
|
129
205
|
id: Optional[str] = None,
|
|
130
|
-
search_request: Optional[SearchRequest] = None,
|
|
206
|
+
search_request: Optional[Union[SearchRequest, Dict]] = None,
|
|
207
|
+
check_request_payload: bool = True,
|
|
208
|
+
check_response_payload: bool = True,
|
|
209
|
+
check_status_code: bool = True,
|
|
131
210
|
**kwargs,
|
|
132
|
-
) -> Union[AnyResource, ListResponse[AnyResource], Error]:
|
|
211
|
+
) -> Union[AnyResource, ListResponse[AnyResource], Error, Dict]:
|
|
133
212
|
"""Perform a GET request to read resources, as defined in :rfc:`RFC7644
|
|
134
213
|
§3.4.2 <7644#section-3.4.2>`.
|
|
135
214
|
|
|
@@ -139,6 +218,11 @@ class SCIMClient:
|
|
|
139
218
|
:param resource_type: A :class:`~scim2_models.Resource` subtype or :data:`None`
|
|
140
219
|
:param id: The SCIM id of an object to get, or :data:`None`
|
|
141
220
|
:param search_request: An object detailing the search query parameters.
|
|
221
|
+
:param check_request_payload: If :data:`False`,
|
|
222
|
+
:code:`search_request` is expected to be a dict that will be passed as-is in the request.
|
|
223
|
+
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
224
|
+
If set, the raw payload will be returned.
|
|
225
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
142
226
|
:param kwargs: Additional parameters passed to the underlying HTTP request library.
|
|
143
227
|
|
|
144
228
|
:return:
|
|
@@ -148,14 +232,18 @@ class SCIMClient:
|
|
|
148
232
|
"""
|
|
149
233
|
|
|
150
234
|
self.check_resource_type(resource_type)
|
|
151
|
-
|
|
152
|
-
search_request
|
|
153
|
-
|
|
154
|
-
|
|
235
|
+
if not check_request_payload:
|
|
236
|
+
payload = search_request
|
|
237
|
+
|
|
238
|
+
else:
|
|
239
|
+
payload = (
|
|
240
|
+
search_request.model_dump(
|
|
241
|
+
exclude_unset=True,
|
|
242
|
+
scim_ctx=Context.RESOURCE_QUERY_REQUEST,
|
|
243
|
+
)
|
|
244
|
+
if search_request
|
|
245
|
+
else None
|
|
155
246
|
)
|
|
156
|
-
if search_request
|
|
157
|
-
else None
|
|
158
|
-
)
|
|
159
247
|
|
|
160
248
|
if not id:
|
|
161
249
|
expected_type = ListResponse[resource_type]
|
|
@@ -165,37 +253,31 @@ class SCIMClient:
|
|
|
165
253
|
expected_type = resource_type
|
|
166
254
|
url = self.resource_endpoint(resource_type) + f"/{id}"
|
|
167
255
|
|
|
168
|
-
expected_status_codes = [
|
|
169
|
-
# Resource querying HTTP codes defined at:
|
|
170
|
-
# https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2
|
|
171
|
-
200,
|
|
172
|
-
400,
|
|
173
|
-
# Default HTTP codes defined at:
|
|
174
|
-
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.12
|
|
175
|
-
307,
|
|
176
|
-
308,
|
|
177
|
-
401,
|
|
178
|
-
403,
|
|
179
|
-
404,
|
|
180
|
-
500,
|
|
181
|
-
]
|
|
182
256
|
response = self.client.get(url, params=payload, **kwargs)
|
|
183
257
|
return self.check_response(
|
|
184
258
|
response,
|
|
185
|
-
|
|
186
|
-
expected_type,
|
|
259
|
+
self.QUERY_RESPONSE_STATUS_CODES if check_status_code else None,
|
|
260
|
+
expected_type if check_response_payload else None,
|
|
187
261
|
scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
|
|
188
262
|
)
|
|
189
263
|
|
|
190
264
|
def query_all(
|
|
191
265
|
self,
|
|
192
266
|
search_request: Optional[SearchRequest] = None,
|
|
267
|
+
check_request_payload: bool = True,
|
|
268
|
+
check_response_payload: bool = True,
|
|
269
|
+
check_status_code: bool = True,
|
|
193
270
|
**kwargs,
|
|
194
|
-
) -> Union[AnyResource, ListResponse[AnyResource], Error]:
|
|
271
|
+
) -> Union[AnyResource, ListResponse[AnyResource], Error, Dict]:
|
|
195
272
|
"""Perform a GET request to read all available resources, as defined in
|
|
196
273
|
:rfc:`RFC7644 §3.4.2.1 <7644#section-3.4.2.1>`.
|
|
197
274
|
|
|
198
275
|
:param search_request: An object detailing the search query parameters.
|
|
276
|
+
:param check_request_payload: If :data:`False`,
|
|
277
|
+
:code:`search_request` is expected to be a dict that will be passed as-is in the request.
|
|
278
|
+
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
279
|
+
If set, the raw payload will be returned.
|
|
280
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
199
281
|
:param kwargs: Additional parameters passed to the underlying
|
|
200
282
|
HTTP request library.
|
|
201
283
|
|
|
@@ -208,49 +290,48 @@ class SCIMClient:
|
|
|
208
290
|
# server SHALL be included, subject to filtering.
|
|
209
291
|
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.4.2.1
|
|
210
292
|
|
|
211
|
-
|
|
212
|
-
search_request
|
|
213
|
-
|
|
293
|
+
if not check_request_payload:
|
|
294
|
+
payload = search_request
|
|
295
|
+
|
|
296
|
+
else:
|
|
297
|
+
payload = (
|
|
298
|
+
search_request.model_dump(
|
|
299
|
+
exclude_unset=True, scim_ctx=Context.RESOURCE_QUERY_REQUEST
|
|
300
|
+
)
|
|
301
|
+
if search_request
|
|
302
|
+
else None
|
|
214
303
|
)
|
|
215
|
-
if search_request
|
|
216
|
-
else None
|
|
217
|
-
)
|
|
218
|
-
response = self.client.get("/", params=payload)
|
|
219
304
|
|
|
220
|
-
|
|
221
|
-
# Resource querying HTTP codes defined at:
|
|
222
|
-
# https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2
|
|
223
|
-
200,
|
|
224
|
-
400,
|
|
225
|
-
# Default HTTP codes defined at:
|
|
226
|
-
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.12
|
|
227
|
-
307,
|
|
228
|
-
308,
|
|
229
|
-
401,
|
|
230
|
-
403,
|
|
231
|
-
404,
|
|
232
|
-
500,
|
|
233
|
-
501,
|
|
234
|
-
]
|
|
305
|
+
response = self.client.get("/", params=payload)
|
|
235
306
|
|
|
236
307
|
return self.check_response(
|
|
237
308
|
response,
|
|
238
|
-
|
|
239
|
-
ListResponse[Union[self.resource_types]]
|
|
309
|
+
self.QUERY_RESPONSE_STATUS_CODES if check_status_code else None,
|
|
310
|
+
ListResponse[Union[self.resource_types]]
|
|
311
|
+
if check_response_payload
|
|
312
|
+
else None,
|
|
240
313
|
scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
|
|
241
314
|
)
|
|
242
315
|
|
|
243
316
|
def search(
|
|
244
317
|
self,
|
|
245
318
|
search_request: Optional[SearchRequest] = None,
|
|
319
|
+
check_request_payload: bool = True,
|
|
320
|
+
check_response_payload: bool = True,
|
|
321
|
+
check_status_code: bool = True,
|
|
246
322
|
**kwargs,
|
|
247
|
-
) -> Union[AnyResource, ListResponse[AnyResource], Error]:
|
|
323
|
+
) -> Union[AnyResource, ListResponse[AnyResource], Error, Dict]:
|
|
248
324
|
"""Perform a POST search request to read all available resources, as
|
|
249
325
|
defined in :rfc:`RFC7644 §3.4.3 <7644#section-3.4.3>`.
|
|
250
326
|
|
|
251
327
|
:param resource_types: Resource type or union of types expected
|
|
252
328
|
to be read from the response.
|
|
253
329
|
:param search_request: An object detailing the search query parameters.
|
|
330
|
+
:param check_request_payload: If :data:`False`,
|
|
331
|
+
:code:`search_request` is expected to be a dict that will be passed as-is in the request.
|
|
332
|
+
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
333
|
+
If set, the raw payload will be returned.
|
|
334
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
254
335
|
:param kwargs: Additional parameters passed to the underlying
|
|
255
336
|
HTTP request library.
|
|
256
337
|
|
|
@@ -259,43 +340,36 @@ class SCIMClient:
|
|
|
259
340
|
- A :class:`~scim2_models.ListResponse[resource_type]` object in case of success.
|
|
260
341
|
"""
|
|
261
342
|
|
|
262
|
-
|
|
263
|
-
search_request
|
|
264
|
-
|
|
343
|
+
if not check_request_payload:
|
|
344
|
+
payload = search_request
|
|
345
|
+
|
|
346
|
+
else:
|
|
347
|
+
payload = (
|
|
348
|
+
search_request.model_dump(
|
|
349
|
+
exclude_unset=True, scim_ctx=Context.RESOURCE_QUERY_RESPONSE
|
|
350
|
+
)
|
|
351
|
+
if search_request
|
|
352
|
+
else None
|
|
265
353
|
)
|
|
266
|
-
|
|
267
|
-
else None
|
|
268
|
-
)
|
|
354
|
+
|
|
269
355
|
response = self.client.post("/.search", params=payload)
|
|
270
356
|
|
|
271
|
-
expected_status_codes = [
|
|
272
|
-
# Resource querying HTTP codes defined at:
|
|
273
|
-
# https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.3
|
|
274
|
-
200,
|
|
275
|
-
# Default HTTP codes defined at:
|
|
276
|
-
# https://datatracker.ietf.org/doc/html/rfc7644.html#section-3.12
|
|
277
|
-
307,
|
|
278
|
-
308,
|
|
279
|
-
400,
|
|
280
|
-
401,
|
|
281
|
-
403,
|
|
282
|
-
404,
|
|
283
|
-
409,
|
|
284
|
-
413,
|
|
285
|
-
500,
|
|
286
|
-
501,
|
|
287
|
-
]
|
|
288
357
|
return self.check_response(
|
|
289
358
|
response,
|
|
290
|
-
|
|
291
|
-
ListResponse[Union[self.resource_types]]
|
|
359
|
+
self.SEARCH_RESPONSE_STATUS_CODES if check_status_code else None,
|
|
360
|
+
ListResponse[Union[self.resource_types]]
|
|
361
|
+
if check_response_payload
|
|
362
|
+
else None,
|
|
292
363
|
scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
|
|
293
364
|
)
|
|
294
365
|
|
|
295
|
-
def delete(
|
|
366
|
+
def delete(
|
|
367
|
+
self, resource_type: Type, id: str, check_status_code: bool = True, **kwargs
|
|
368
|
+
) -> Optional[Union[Error, Dict]]:
|
|
296
369
|
"""Perform a DELETE request to create, as defined in :rfc:`RFC7644 §3.6
|
|
297
370
|
<7644#section-3.6>`.
|
|
298
371
|
|
|
372
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
299
373
|
:param kwargs: Additional parameters passed to the underlying
|
|
300
374
|
HTTP request library.
|
|
301
375
|
|
|
@@ -308,29 +382,27 @@ class SCIMClient:
|
|
|
308
382
|
url = self.resource_endpoint(resource_type) + f"/{id}"
|
|
309
383
|
response = self.client.delete(url, **kwargs)
|
|
310
384
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
412,
|
|
324
|
-
500,
|
|
325
|
-
501,
|
|
326
|
-
]
|
|
327
|
-
return self.check_response(response, expected_status_codes)
|
|
328
|
-
|
|
329
|
-
def replace(self, resource: AnyResource, **kwargs) -> Union[AnyResource, Error]:
|
|
385
|
+
return self.check_response(
|
|
386
|
+
response, self.DELETION_RESPONSE_STATUS_CODES if check_status_code else None
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
def replace(
|
|
390
|
+
self,
|
|
391
|
+
resource: Union[AnyResource, Dict],
|
|
392
|
+
check_request_payload: bool = True,
|
|
393
|
+
check_response_payload: bool = True,
|
|
394
|
+
check_status_code: bool = True,
|
|
395
|
+
**kwargs,
|
|
396
|
+
) -> Union[AnyResource, Error, Dict]:
|
|
330
397
|
"""Perform a PUT request to replace a resource, as defined in
|
|
331
398
|
:rfc:`RFC7644 §3.5.1 <7644#section-3.5.1>`.
|
|
332
399
|
|
|
333
400
|
:param resource: The new state of the resource to replace.
|
|
401
|
+
:param check_request_payload: If :data:`False`,
|
|
402
|
+
:code:`resource` is expected to be a dict that will be passed as-is in the request.
|
|
403
|
+
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
404
|
+
If set, the raw payload will be returned.
|
|
405
|
+
:param check_status_code: Whether to validate that the response status code is valid.
|
|
334
406
|
:param kwargs: Additional parameters passed to the underlying
|
|
335
407
|
HTTP request library.
|
|
336
408
|
|
|
@@ -339,39 +411,32 @@ class SCIMClient:
|
|
|
339
411
|
- The updated object as returned by the server in case of success.
|
|
340
412
|
"""
|
|
341
413
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
400,
|
|
359
|
-
401,
|
|
360
|
-
403,
|
|
361
|
-
404,
|
|
362
|
-
409,
|
|
363
|
-
412,
|
|
364
|
-
500,
|
|
365
|
-
501,
|
|
366
|
-
]
|
|
414
|
+
if not check_request_payload:
|
|
415
|
+
payload = resource
|
|
416
|
+
url = kwargs.pop("url")
|
|
417
|
+
|
|
418
|
+
else:
|
|
419
|
+
self.check_resource_type(resource.__class__)
|
|
420
|
+
if not resource.id:
|
|
421
|
+
raise Exception("Resource must have an id")
|
|
422
|
+
|
|
423
|
+
payload = resource.model_dump(scim_ctx=Context.RESOURCE_REPLACEMENT_REQUEST)
|
|
424
|
+
url = kwargs.pop(
|
|
425
|
+
"url", self.resource_endpoint(resource.__class__) + f"/{resource.id}"
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
response = self.client.put(url, json=payload, **kwargs)
|
|
429
|
+
|
|
367
430
|
return self.check_response(
|
|
368
431
|
response,
|
|
369
|
-
|
|
370
|
-
resource.__class__
|
|
432
|
+
self.REPLACEMENT_RESPONSE_STATUS_CODES if check_status_code else None,
|
|
433
|
+
resource.__class__
|
|
434
|
+
if check_request_payload and check_response_payload
|
|
435
|
+
else None,
|
|
371
436
|
scim_ctx=Context.RESOURCE_REPLACEMENT_RESPONSE,
|
|
372
437
|
)
|
|
373
438
|
|
|
374
439
|
def modify(
|
|
375
|
-
self, resource: AnyResource, op: PatchOp, **kwargs
|
|
376
|
-
) -> Optional[AnyResource]:
|
|
440
|
+
self, resource: Union[AnyResource, Dict], op: PatchOp, **kwargs
|
|
441
|
+
) -> Optional[Union[AnyResource, Dict]]:
|
|
377
442
|
raise NotImplementedError()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scim2-client
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Pythonically build SCIM requests and parse SCIM responses
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: scim,scim2,provisioning,httpx,api
|
|
@@ -42,7 +42,7 @@ Here is an example of usage:
|
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
44
|
import datetime
|
|
45
|
-
from httpx
|
|
45
|
+
from httpx import Client
|
|
46
46
|
from scim2_models import User, EnterpriseUserUser, Group, Error
|
|
47
47
|
from scim2_client import SCIMClient
|
|
48
48
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
scim2_client/__init__.py,sha256=2UNsl6HNtVUv5LVcnmLaCHyT4SqAUUFOIWW2r5XGv6A,338
|
|
2
|
+
scim2_client/client.py,sha256=_ZjMd6_Kh5SYEcstm5OkMIu0z-N93R4SWdG0lGd4u7s,16538
|
|
3
|
+
scim2_client/errors.py,sha256=uOOAwsD8rDrC8BQbwPid051YyWtexTcS8b7i6QC6-CM,1175
|
|
4
|
+
scim2_client-0.1.2.dist-info/METADATA,sha256=4h7QD3jpYRhSQCBmLX9AFhHJ9R68_ObP45V9_kV51LI,2654
|
|
5
|
+
scim2_client-0.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
6
|
+
scim2_client-0.1.2.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
scim2_client/__init__.py,sha256=2UNsl6HNtVUv5LVcnmLaCHyT4SqAUUFOIWW2r5XGv6A,338
|
|
2
|
-
scim2_client/client.py,sha256=LsG_omH6Mz4mxcqLLA6ApnVJqInAWo8GjaVRXuyf08c,13199
|
|
3
|
-
scim2_client/errors.py,sha256=uOOAwsD8rDrC8BQbwPid051YyWtexTcS8b7i6QC6-CM,1175
|
|
4
|
-
scim2_client-0.1.1.dist-info/METADATA,sha256=s1A7Uk7fz_9n0PgU7V2EqxGZMEonmfCzVod5a7l_sJ4,2654
|
|
5
|
-
scim2_client-0.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
6
|
-
scim2_client-0.1.1.dist-info/RECORD,,
|
|
File without changes
|