scim2-cli 0.2.1__tar.gz → 0.2.3__tar.gz
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_cli-0.2.1 → scim2_cli-0.2.3}/.github/workflows/release.yml +11 -1
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/.github/workflows/tests.yaml +10 -0
- scim2_cli-0.2.3/.hgignore +1 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/.pre-commit-config.yaml +1 -1
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/PKG-INFO +5 -4
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/changelog.rst +15 -0
- scim2_cli-0.2.3/doc/tutorial.rst +250 -0
- scim2_cli-0.2.3/flake.lock +133 -0
- scim2_cli-0.2.3/flake.nix +70 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/pyproject.toml +3 -3
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/__init__.py +14 -23
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/test.py +21 -1
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_test.py +9 -2
- scim2_cli-0.2.3/uv.lock +1385 -0
- scim2_cli-0.2.1/doc/tutorial.rst +0 -75
- scim2_cli-0.2.1/uv.lock +0 -1342
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/.github/FUNDING.yml +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/.gitignore +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/.readthedocs.yml +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/LICENSE.md +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/README.md +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/__init__.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/conf.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/contributing.rst +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/index.rst +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/doc/reference.rst +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/create.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/delete.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/py.typed +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/query.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/replace.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/search.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/scim2_cli/utils.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/__init__.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/conftest.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_cli.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_create.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_delete.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_query.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_replace.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_search.py +0 -0
- {scim2_cli-0.2.1 → scim2_cli-0.2.3}/tests/test_utils.py +0 -0
|
@@ -16,8 +16,12 @@ jobs:
|
|
|
16
16
|
uses: astral-sh/setup-uv@v3
|
|
17
17
|
with:
|
|
18
18
|
enable-cache: true
|
|
19
|
+
- name: build dist
|
|
20
|
+
run: uv sync --group bundle
|
|
19
21
|
- name: build dist
|
|
20
22
|
run: uv build
|
|
23
|
+
- name: build binary
|
|
24
|
+
run: uv run pyinstaller scim2.spec
|
|
21
25
|
- uses: actions/upload-artifact@v4
|
|
22
26
|
with:
|
|
23
27
|
name: artifacts
|
|
@@ -28,8 +32,14 @@ jobs:
|
|
|
28
32
|
name: create Github release
|
|
29
33
|
runs-on: ubuntu-latest
|
|
30
34
|
steps:
|
|
35
|
+
- uses: actions/download-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: artifacts
|
|
38
|
+
path: dist
|
|
31
39
|
- uses: softprops/action-gh-release@v2
|
|
32
|
-
|
|
40
|
+
with:
|
|
41
|
+
files: |
|
|
42
|
+
dist/scim2
|
|
33
43
|
publish:
|
|
34
44
|
name: release to pypi
|
|
35
45
|
needs: build
|
|
@@ -65,3 +65,13 @@ jobs:
|
|
|
65
65
|
- name: Install dependencies
|
|
66
66
|
run: uv sync --group doc
|
|
67
67
|
- run: uv run sphinx-build doc build/sphinx/html
|
|
68
|
+
|
|
69
|
+
nix:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
- uses: cachix/install-nix-action@v27
|
|
74
|
+
with:
|
|
75
|
+
github_access_token: ${{ secrets.GITHUB_TOKEN }}
|
|
76
|
+
- run: nix build
|
|
77
|
+
- run: nix flake check
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.dotfiles/mercurial/.hgignore
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: scim2-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: SCIM application development CLI
|
|
5
5
|
Project-URL: documentation, https://scim2-cli.readthedocs.io
|
|
6
6
|
Project-URL: repository, https://github.com/python-scim/scim2-cli
|
|
@@ -208,6 +208,7 @@ License: Apache License
|
|
|
208
208
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
209
209
|
See the License for the specific language governing permissions and
|
|
210
210
|
limitations under the License.
|
|
211
|
+
License-File: LICENSE.md
|
|
211
212
|
Keywords: provisioning,rfc7643,rfc7644,scim,scim2
|
|
212
213
|
Classifier: Development Status :: 3 - Alpha
|
|
213
214
|
Classifier: Environment :: Web Environment
|
|
@@ -222,9 +223,9 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
222
223
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
223
224
|
Requires-Python: >=3.10
|
|
224
225
|
Requires-Dist: click>=8.1.7
|
|
225
|
-
Requires-Dist: pydanclick>=0.
|
|
226
|
+
Requires-Dist: pydanclick>=0.4.0
|
|
226
227
|
Requires-Dist: pygments>=2.18.0
|
|
227
|
-
Requires-Dist: scim2-client>=0.4.
|
|
228
|
+
Requires-Dist: scim2-client>=0.4.3
|
|
228
229
|
Requires-Dist: scim2-tester[httpx]>=0.1.10
|
|
229
230
|
Requires-Dist: sphinx-click-rst-to-ansi-formatter>=0.1.0
|
|
230
231
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
[0.2.3] - 2025-03-06
|
|
5
|
+
--------------------
|
|
6
|
+
|
|
7
|
+
Added
|
|
8
|
+
^^^^^
|
|
9
|
+
- Add the ``--no-verify`` parameter to skip certificate verifications. :issue:`20`
|
|
10
|
+
|
|
11
|
+
[0.2.2] - 2024-12-06
|
|
12
|
+
--------------------
|
|
13
|
+
|
|
14
|
+
Added
|
|
15
|
+
^^^^^
|
|
16
|
+
- The :ref:`test` command returns 1 in case of errors.
|
|
17
|
+
- Added :ref:`test` ``--dont-check-content-type`` and ``--dont-check-status-code`` options.
|
|
18
|
+
|
|
4
19
|
[0.2.1] - 2024-12-04
|
|
5
20
|
--------------------
|
|
6
21
|
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Tutorial
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
The :ref:`cli` command allows you to interact with a SCIM server.
|
|
5
|
+
|
|
6
|
+
.. tip::
|
|
7
|
+
|
|
8
|
+
If you want to test scim2-cli with a real SCIM server, you can install and run `scim2-server <https://github.com/python-scim/scim2-server>`__:
|
|
9
|
+
|
|
10
|
+
.. code-block:: shell
|
|
11
|
+
|
|
12
|
+
$ pip install scim2-server
|
|
13
|
+
$ scim2-server
|
|
14
|
+
|
|
15
|
+
Then you have a functional SCIM server available at http://127.0.0.1:8080 that you can use to test the different commands.
|
|
16
|
+
|
|
17
|
+
Basic parameters
|
|
18
|
+
----------------
|
|
19
|
+
|
|
20
|
+
In order to connect to a SCIM server you will need to pass the :option:`--url <scim --url>` parameter.
|
|
21
|
+
You can also pass additional headers, such as authentication ones, with :option:`--header <scim --header>`.
|
|
22
|
+
|
|
23
|
+
.. code-block:: shell
|
|
24
|
+
|
|
25
|
+
$ scim2 --url https://auth.example --header "Authorization: Bearer 12345" create user --user-name "bjensen@example.com"
|
|
26
|
+
{
|
|
27
|
+
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
|
28
|
+
"id": "2819c223-7f76-453a-919d-413861904646",
|
|
29
|
+
"userName": "bjensen@example.com",
|
|
30
|
+
"meta": {
|
|
31
|
+
"resourceType": "User",
|
|
32
|
+
"created": "2010-01-23T04:56:22Z",
|
|
33
|
+
"lastModified": "2011-05-13T04:42:34Z",
|
|
34
|
+
"version": 'W\\/"3694e05e9dff590"',
|
|
35
|
+
"location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
However passing those parameters each time you use the command can be annoying.
|
|
40
|
+
To make commands shorter, you can set those parameters once for all by using the :ref:`SCIM_CLI_URL <scim-url-scim_cli_url>` and :ref:`SCIM_CLI_HEADERS <scim-header-scim_cli_headers>` environment vars.
|
|
41
|
+
|
|
42
|
+
.. code-block:: shell
|
|
43
|
+
|
|
44
|
+
$ export SCIM_CLI_URL="https://auth.example"
|
|
45
|
+
$ export SCIM_CLI_HEADERS="Authorization: Bearer 12345"
|
|
46
|
+
$ scim2 create user --user-name "bjensen@example.com"
|
|
47
|
+
{
|
|
48
|
+
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
|
49
|
+
"id": "2819c223-7f76-453a-919d-413861904646",
|
|
50
|
+
"userName": "bjensen@example.com",
|
|
51
|
+
"meta": {
|
|
52
|
+
"resourceType": "User",
|
|
53
|
+
"created": "2010-01-23T04:56:22Z",
|
|
54
|
+
"lastModified": "2011-05-13T04:42:34Z",
|
|
55
|
+
"version": 'W\\/"3694e05e9dff590"',
|
|
56
|
+
"location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
Server configuration
|
|
62
|
+
--------------------
|
|
63
|
+
|
|
64
|
+
Before doing anything, the CLI needs to reach the server configuration to find out which features are available,
|
|
65
|
+
which resource schemas are available, and where they are located.
|
|
66
|
+
|
|
67
|
+
By default the CLI will automatically discover those resources on the server, before each command is run.
|
|
68
|
+
|
|
69
|
+
However you might find too time consuming to achieve all those network requests.
|
|
70
|
+
You can store those data locally and reuse them for future command runs thanks to the
|
|
71
|
+
:option:`--schemas <scim --schemas>`, :option:`--resource-types <scim --resource-types>` and :option:`--service-provider-config <scim --service-provider-config>` (and their corresponding environment vars :ref:`SCIM_CLI_SCHEMAS <scim-schemas-scim_cli_schemas>`, :ref:`SCIM_CLI_RESOURCE_TYPES <scim-resource_types-scim_cli_resource_types>` and :ref:`SCIM_CLI_SERVICE_PROVIDER_CONFIG <scim-service_provider_config-scim_cli_service_provider_config>`)
|
|
72
|
+
|
|
73
|
+
.. code-block:: shell
|
|
74
|
+
:caption: Save the configuration resources
|
|
75
|
+
|
|
76
|
+
$ scim query schema > /tmp/schemas.json
|
|
77
|
+
$ scim query resourcetype > /tmp/resource-types.json
|
|
78
|
+
$ scim query serviceproviderconfig > /tmp/service-provider-config.json
|
|
79
|
+
|
|
80
|
+
.. code-block:: shell
|
|
81
|
+
:caption: Load the cached resources
|
|
82
|
+
|
|
83
|
+
$ export SCIM_SCHEMAS=/tmp/schemas.json
|
|
84
|
+
$ export SCIM_RESOURCE_TYPES=/tmp/resource-types.json
|
|
85
|
+
$ export SCIM_SERVICE_PROVIDER_CONFIG=/tmp/service-provider-config.json
|
|
86
|
+
$ scim2 query ...
|
|
87
|
+
|
|
88
|
+
Query and search resources
|
|
89
|
+
--------------------------
|
|
90
|
+
|
|
91
|
+
The :ref:`query` and :ref:`search` commands can be used to look for resources.
|
|
92
|
+
:ref:`query` performs ag `GET` request on the resources endpoint, while :ref:`search` performs a `POST` request on the ``/.search`` endpoint.
|
|
93
|
+
Both commands take similar options such as :option:`--count <scim-query.--count>` or :option:`--attributes <scim-query.--attributes>`.
|
|
94
|
+
An exhaustive list of options can be found on the :doc:`reference`.
|
|
95
|
+
:ref:`query` can also take a :option:`RESOURCE_TYPE <scim-query.RESOURCE_TYPE>` and a :option:`ID <scim-query.ID>` parameters.
|
|
96
|
+
|
|
97
|
+
- If none are set, all the resources of the server are queried.
|
|
98
|
+
|
|
99
|
+
.. code-block:: console
|
|
100
|
+
:caption: Querying all the resources from the server.
|
|
101
|
+
|
|
102
|
+
$ scim query
|
|
103
|
+
{
|
|
104
|
+
"schemas": [
|
|
105
|
+
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
|
|
106
|
+
],
|
|
107
|
+
"totalResults": xx,
|
|
108
|
+
"startIndex": 1,
|
|
109
|
+
"itemsPerPage": 50,
|
|
110
|
+
"Resources": [...]
|
|
111
|
+
}
|
|
112
|
+
- If :option:`RESOURCE_TYPE <scim-query.RESOURCE_TYPE>` is set and :option:`ID <scim-query.ID>` is unset, all the resource of the kind passed in parameter are returned.
|
|
113
|
+
|
|
114
|
+
.. code-block:: console
|
|
115
|
+
:caption: Querying all the users from the server.
|
|
116
|
+
|
|
117
|
+
$ scim query user
|
|
118
|
+
{
|
|
119
|
+
"schemas": [
|
|
120
|
+
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
|
|
121
|
+
],
|
|
122
|
+
"totalResults": xx,
|
|
123
|
+
"startIndex": 1,
|
|
124
|
+
"itemsPerPage": 50,
|
|
125
|
+
"Resources": [...]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
- If both options are set, the very resource with the ID are returned.
|
|
129
|
+
|
|
130
|
+
.. code-block:: console
|
|
131
|
+
:caption: Querying the user with the ID `38b044dd95624c4186f5614fca30305d`
|
|
132
|
+
|
|
133
|
+
$ scim query user 38b044dd95624c4186f5614fca30305d
|
|
134
|
+
{
|
|
135
|
+
"schemas": [
|
|
136
|
+
"urn:ietf:params:scim:schemas:core:2.0:User",
|
|
137
|
+
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
|
|
138
|
+
],
|
|
139
|
+
"id": "38b044dd95624c4186f5614fca30305d",
|
|
140
|
+
"meta": {
|
|
141
|
+
"resourceType": "User",
|
|
142
|
+
"created": "2024-12-05T16:08:51.896646Z",
|
|
143
|
+
"lastModified": "2024-12-05T16:08:51.896646Z",
|
|
144
|
+
"location": "http://scim.example/v2/Users/38b044dd95624c4186f5614fca30305d",
|
|
145
|
+
"version": "W/\"637b1ce03c010cd55fe45b6f7be2247b5159b135\""
|
|
146
|
+
},
|
|
147
|
+
"userName": "bjensen@example.com"
|
|
148
|
+
}
|
|
149
|
+
Create and replace resources
|
|
150
|
+
----------------------------
|
|
151
|
+
|
|
152
|
+
The :ref:`create` and :ref:`replace` commands can be used to edit resources.
|
|
153
|
+
|
|
154
|
+
Options for those commands are dynamically generated, depending on the resource attributes available on the server.
|
|
155
|
+
For instance, for the :class:`~scim2_models.User` resource, you have a ``--user-name`` option.
|
|
156
|
+
You can have a look at the exhaustive list of options by running ``scim create user --help``.
|
|
157
|
+
|
|
158
|
+
.. code-block:: console
|
|
159
|
+
:caption: Creation of an user.
|
|
160
|
+
|
|
161
|
+
$ scim create user --user-name bjensen@example.com
|
|
162
|
+
{
|
|
163
|
+
"schemas": [
|
|
164
|
+
"urn:ietf:params:scim:schemas:core:2.0:User",
|
|
165
|
+
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
|
|
166
|
+
],
|
|
167
|
+
"id": "38b044dd95624c4186f5614fca30305d",
|
|
168
|
+
"meta": {
|
|
169
|
+
"resourceType": "User",
|
|
170
|
+
"created": "2024-12-05T16:08:51.896646Z",
|
|
171
|
+
"lastModified": "2024-12-05T16:08:51.896646Z",
|
|
172
|
+
"location": "http://scim.example/v2/Users/38b044dd95624c4186f5614fca30305d",
|
|
173
|
+
"version": "W/\"637b1ce03c010cd55fe45b6f7be2247b5159b135\""
|
|
174
|
+
},
|
|
175
|
+
"userName": "bjensen@example.com"
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Delete resources
|
|
179
|
+
----------------
|
|
180
|
+
|
|
181
|
+
The :ref:`delete` command allows you to delete resources.
|
|
182
|
+
|
|
183
|
+
.. code-block:: console
|
|
184
|
+
:caption: Deletion of an user.
|
|
185
|
+
|
|
186
|
+
$ scim delete user 38b044dd95624c4186f5614fca30305d
|
|
187
|
+
|
|
188
|
+
Perform a SCIM compliance test
|
|
189
|
+
------------------------------
|
|
190
|
+
|
|
191
|
+
The :ref:`test` command runs a series of resource creation, edition and deletions to check that your server complies with the SCIM specifications.
|
|
192
|
+
See the :doc:`scim2-tester documentation <scim2_tester:index>` for more details on which tests are performed.
|
|
193
|
+
|
|
194
|
+
.. code-block:: console
|
|
195
|
+
:caption: SCIM compliance test
|
|
196
|
+
|
|
197
|
+
$ scim test
|
|
198
|
+
Performing a SCIM compliance check on http://localhost:8080 ...
|
|
199
|
+
SUCCESS check_service_provider_config_endpoint
|
|
200
|
+
SUCCESS check_query_all_resource_types
|
|
201
|
+
SUCCESS check_query_resource_type_by_id
|
|
202
|
+
Successfully accessed the /ResourceTypes/User endpoint.
|
|
203
|
+
SUCCESS check_query_resource_type_by_id
|
|
204
|
+
Successfully accessed the /ResourceTypes/Group endpoint.
|
|
205
|
+
SUCCESS check_access_invalid_resource_typ
|
|
206
|
+
...
|
|
207
|
+
|
|
208
|
+
JSON input
|
|
209
|
+
----------
|
|
210
|
+
|
|
211
|
+
scim2-cli will also read input data from the standard input.
|
|
212
|
+
This can be used to send custom payloads to the SCIM server.
|
|
213
|
+
|
|
214
|
+
When user with :ref:`query` and :ref:`search`, the input value must be a JSON representation of a :class:`~scim2_models.SearchRequest` object:
|
|
215
|
+
|
|
216
|
+
.. code-block:: console
|
|
217
|
+
:caption: Search of an user by passing a custom payload.
|
|
218
|
+
|
|
219
|
+
$ echo '{"startIndex": 50, "count": 10}' | scim query user
|
|
220
|
+
{
|
|
221
|
+
"schemas": [
|
|
222
|
+
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
|
|
223
|
+
],
|
|
224
|
+
"totalResults": xx,
|
|
225
|
+
"startIndex": 50,
|
|
226
|
+
"itemsPerPage": 10,
|
|
227
|
+
"Resources": [...]
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
When used with :ref:`create` and :ref:`replace`, no subcommand is needed and the endpoint is guessed from the payload.
|
|
231
|
+
|
|
232
|
+
.. code-block:: console
|
|
233
|
+
:caption: Creation of an user by passing a custom payload.
|
|
234
|
+
|
|
235
|
+
$ echo '{"userName": "bjensen@example.com", "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"]}' | scim create
|
|
236
|
+
{
|
|
237
|
+
"schemas": [
|
|
238
|
+
"urn:ietf:params:scim:schemas:core:2.0:User",
|
|
239
|
+
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
|
|
240
|
+
],
|
|
241
|
+
"id": "38b044dd95624c4186f5614fca30305d",
|
|
242
|
+
"meta": {
|
|
243
|
+
"resourceType": "User",
|
|
244
|
+
"created": "2024-12-05T16:08:51.896646Z",
|
|
245
|
+
"lastModified": "2024-12-05T16:08:51.896646Z",
|
|
246
|
+
"location": "http://scim.example/v2/Users/38b044dd95624c4186f5614fca30305d",
|
|
247
|
+
"version": "W/\"637b1ce03c010cd55fe45b6f7be2247b5159b135\""
|
|
248
|
+
},
|
|
249
|
+
"userName": "bjensen@example.com"
|
|
250
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nodes": {
|
|
3
|
+
"flake-utils": {
|
|
4
|
+
"inputs": {
|
|
5
|
+
"systems": "systems"
|
|
6
|
+
},
|
|
7
|
+
"locked": {
|
|
8
|
+
"lastModified": 1731533236,
|
|
9
|
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
10
|
+
"owner": "numtide",
|
|
11
|
+
"repo": "flake-utils",
|
|
12
|
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
13
|
+
"type": "github"
|
|
14
|
+
},
|
|
15
|
+
"original": {
|
|
16
|
+
"owner": "numtide",
|
|
17
|
+
"repo": "flake-utils",
|
|
18
|
+
"type": "github"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"nixpkgs": {
|
|
22
|
+
"locked": {
|
|
23
|
+
"lastModified": 1738680400,
|
|
24
|
+
"narHash": "sha256-ooLh+XW8jfa+91F1nhf9OF7qhuA/y1ChLx6lXDNeY5U=",
|
|
25
|
+
"owner": "NixOS",
|
|
26
|
+
"repo": "nixpkgs",
|
|
27
|
+
"rev": "799ba5bffed04ced7067a91798353d360788b30d",
|
|
28
|
+
"type": "github"
|
|
29
|
+
},
|
|
30
|
+
"original": {
|
|
31
|
+
"owner": "NixOS",
|
|
32
|
+
"ref": "nixos-unstable",
|
|
33
|
+
"repo": "nixpkgs",
|
|
34
|
+
"type": "github"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"pyproject-build-systems": {
|
|
38
|
+
"inputs": {
|
|
39
|
+
"nixpkgs": [
|
|
40
|
+
"nixpkgs"
|
|
41
|
+
],
|
|
42
|
+
"pyproject-nix": [
|
|
43
|
+
"pyproject-nix"
|
|
44
|
+
],
|
|
45
|
+
"uv2nix": [
|
|
46
|
+
"uv2nix"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"locked": {
|
|
50
|
+
"lastModified": 1737338290,
|
|
51
|
+
"narHash": "sha256-gnXlfFEHA+/jMH7R+7y3JxrI3WfOjgBhzzJNuFW70UU=",
|
|
52
|
+
"owner": "pyproject-nix",
|
|
53
|
+
"repo": "build-system-pkgs",
|
|
54
|
+
"rev": "e1487e5cefda0c7990bdd2e660bee20971680e45",
|
|
55
|
+
"type": "github"
|
|
56
|
+
},
|
|
57
|
+
"original": {
|
|
58
|
+
"owner": "pyproject-nix",
|
|
59
|
+
"repo": "build-system-pkgs",
|
|
60
|
+
"type": "github"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"pyproject-nix": {
|
|
64
|
+
"inputs": {
|
|
65
|
+
"nixpkgs": [
|
|
66
|
+
"nixpkgs"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"locked": {
|
|
70
|
+
"lastModified": 1738204167,
|
|
71
|
+
"narHash": "sha256-J5M2sj3x4ocM93shScT/3Z4XWHZhwwW1NyQK+C+8Mys=",
|
|
72
|
+
"owner": "pyproject-nix",
|
|
73
|
+
"repo": "pyproject.nix",
|
|
74
|
+
"rev": "0d9f4b90cee1b5c5d6c142ef22de1e246e003ccc",
|
|
75
|
+
"type": "github"
|
|
76
|
+
},
|
|
77
|
+
"original": {
|
|
78
|
+
"owner": "pyproject-nix",
|
|
79
|
+
"repo": "pyproject.nix",
|
|
80
|
+
"type": "github"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"root": {
|
|
84
|
+
"inputs": {
|
|
85
|
+
"flake-utils": "flake-utils",
|
|
86
|
+
"nixpkgs": "nixpkgs",
|
|
87
|
+
"pyproject-build-systems": "pyproject-build-systems",
|
|
88
|
+
"pyproject-nix": "pyproject-nix",
|
|
89
|
+
"uv2nix": "uv2nix"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"systems": {
|
|
93
|
+
"locked": {
|
|
94
|
+
"lastModified": 1681028828,
|
|
95
|
+
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
96
|
+
"owner": "nix-systems",
|
|
97
|
+
"repo": "default",
|
|
98
|
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
99
|
+
"type": "github"
|
|
100
|
+
},
|
|
101
|
+
"original": {
|
|
102
|
+
"owner": "nix-systems",
|
|
103
|
+
"repo": "default",
|
|
104
|
+
"type": "github"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"uv2nix": {
|
|
108
|
+
"inputs": {
|
|
109
|
+
"nixpkgs": [
|
|
110
|
+
"nixpkgs"
|
|
111
|
+
],
|
|
112
|
+
"pyproject-nix": [
|
|
113
|
+
"pyproject-nix"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"locked": {
|
|
117
|
+
"lastModified": 1738653454,
|
|
118
|
+
"narHash": "sha256-tAFX8mPZtZ+zVE/+bwPC3U+u5MxjpNP0gG24DG26jVs=",
|
|
119
|
+
"owner": "pyproject-nix",
|
|
120
|
+
"repo": "uv2nix",
|
|
121
|
+
"rev": "05b0c148bc53aebc6a906b6d0ac41dde5954cd47",
|
|
122
|
+
"type": "github"
|
|
123
|
+
},
|
|
124
|
+
"original": {
|
|
125
|
+
"owner": "pyproject-nix",
|
|
126
|
+
"repo": "uv2nix",
|
|
127
|
+
"type": "github"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"root": "root",
|
|
132
|
+
"version": 7
|
|
133
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
inputs = {
|
|
3
|
+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
4
|
+
flake-utils.url = "github:numtide/flake-utils";
|
|
5
|
+
pyproject-nix = {
|
|
6
|
+
url = "github:pyproject-nix/pyproject.nix";
|
|
7
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
8
|
+
};
|
|
9
|
+
uv2nix = {
|
|
10
|
+
url = "github:pyproject-nix/uv2nix";
|
|
11
|
+
inputs.pyproject-nix.follows = "pyproject-nix";
|
|
12
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
13
|
+
};
|
|
14
|
+
pyproject-build-systems = {
|
|
15
|
+
url = "github:pyproject-nix/build-system-pkgs";
|
|
16
|
+
inputs.pyproject-nix.follows = "pyproject-nix";
|
|
17
|
+
inputs.uv2nix.follows = "uv2nix";
|
|
18
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
outputs =
|
|
23
|
+
{
|
|
24
|
+
self,
|
|
25
|
+
nixpkgs,
|
|
26
|
+
flake-utils,
|
|
27
|
+
uv2nix,
|
|
28
|
+
pyproject-nix,
|
|
29
|
+
pyproject-build-systems,
|
|
30
|
+
...
|
|
31
|
+
}:
|
|
32
|
+
flake-utils.lib.eachDefaultSystem (
|
|
33
|
+
system:
|
|
34
|
+
let
|
|
35
|
+
inherit (nixpkgs) lib;
|
|
36
|
+
|
|
37
|
+
workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
|
|
38
|
+
|
|
39
|
+
overlay = workspace.mkPyprojectOverlay {
|
|
40
|
+
sourcePreference = "wheel";
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
pkgs = nixpkgs.legacyPackages.${system};
|
|
44
|
+
|
|
45
|
+
python = pkgs.python312;
|
|
46
|
+
|
|
47
|
+
pythonSet =
|
|
48
|
+
(pkgs.callPackage pyproject-nix.build.packages {
|
|
49
|
+
inherit python;
|
|
50
|
+
}).overrideScope
|
|
51
|
+
(
|
|
52
|
+
lib.composeManyExtensions [
|
|
53
|
+
pyproject-build-systems.overlays.default
|
|
54
|
+
overlay
|
|
55
|
+
]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
in
|
|
59
|
+
{
|
|
60
|
+
packages.default = pythonSet.mkVirtualEnv "scim-cli-env" workspace.deps.default;
|
|
61
|
+
|
|
62
|
+
apps = {
|
|
63
|
+
default = {
|
|
64
|
+
type = "app";
|
|
65
|
+
program = "${self.packages.${system}.default}/bin/scim2";
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "SCIM application development CLI"
|
|
9
9
|
authors = [{name="Yaal Coop", email="contact@yaal.coop"}]
|
|
10
10
|
license = {file = "LICENSE.md"}
|
|
@@ -27,10 +27,10 @@ classifiers = [
|
|
|
27
27
|
requires-python = ">= 3.10"
|
|
28
28
|
dependencies = [
|
|
29
29
|
"click>=8.1.7",
|
|
30
|
-
"scim2-client>=0.4.
|
|
30
|
+
"scim2-client>=0.4.3",
|
|
31
31
|
"scim2-tester[httpx]>=0.1.10",
|
|
32
32
|
"sphinx-click-rst-to-ansi-formatter>=0.1.0",
|
|
33
|
-
"pydanclick>=0.
|
|
33
|
+
"pydanclick>=0.4.0",
|
|
34
34
|
"pygments>=2.18.0",
|
|
35
35
|
]
|
|
36
36
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
|
-
from typing import Any
|
|
4
|
-
from typing import TypeGuard
|
|
5
3
|
|
|
6
4
|
import click
|
|
7
5
|
from httpx import Client
|
|
8
|
-
from pydantic import BaseModel
|
|
9
6
|
from scim2_client import SCIMClientError
|
|
10
7
|
from scim2_client.engines.httpx import SyncSCIMClient
|
|
11
8
|
from scim2_models import Group
|
|
@@ -29,24 +26,6 @@ from scim2_cli.utils import exception_to_click_error
|
|
|
29
26
|
from scim2_cli.utils import split_headers
|
|
30
27
|
|
|
31
28
|
|
|
32
|
-
# monkeypatching pydanclick until this patch is released
|
|
33
|
-
# https://github.com/felix-martel/pydanclick/pull/25
|
|
34
|
-
def patch_pydanclick():
|
|
35
|
-
def _is_pydantic_model(model: Any) -> TypeGuard[type[BaseModel]]:
|
|
36
|
-
"""Return True if `model` is a Pydantic `BaseModel` class."""
|
|
37
|
-
try:
|
|
38
|
-
return issubclass(model, BaseModel)
|
|
39
|
-
except TypeError:
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
import pydanclick.model.field_collection
|
|
43
|
-
|
|
44
|
-
pydanclick.model.field_collection._is_pydantic_model = _is_pydantic_model
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
patch_pydanclick()
|
|
48
|
-
|
|
49
|
-
|
|
50
29
|
def load_config_files(
|
|
51
30
|
schemas_fd, resource_types_fd, service_provider_config_fd
|
|
52
31
|
) -> tuple[
|
|
@@ -97,6 +76,12 @@ def load_config_files(
|
|
|
97
76
|
help="Headers to pass in the HTTP requests. Can be passed multiple times.",
|
|
98
77
|
envvar="SCIM_CLI_HEADERS",
|
|
99
78
|
)
|
|
79
|
+
@click.option(
|
|
80
|
+
"--no-verify",
|
|
81
|
+
is_flag=True,
|
|
82
|
+
default=False,
|
|
83
|
+
help="Don't perform https certificate verifications.",
|
|
84
|
+
)
|
|
100
85
|
@click.option(
|
|
101
86
|
"-s",
|
|
102
87
|
"--schemas",
|
|
@@ -120,7 +105,13 @@ def load_config_files(
|
|
|
120
105
|
)
|
|
121
106
|
@click.pass_context
|
|
122
107
|
def cli(
|
|
123
|
-
ctx,
|
|
108
|
+
ctx,
|
|
109
|
+
url: str,
|
|
110
|
+
header: list[str],
|
|
111
|
+
no_verify,
|
|
112
|
+
schemas,
|
|
113
|
+
resource_types,
|
|
114
|
+
service_provider_config,
|
|
124
115
|
):
|
|
125
116
|
"""SCIM application development CLI."""
|
|
126
117
|
ctx.ensure_object(dict)
|
|
@@ -129,7 +120,7 @@ def cli(
|
|
|
129
120
|
raise click.ClickException("No SCIM server URL defined.")
|
|
130
121
|
|
|
131
122
|
headers_dict = split_headers(header)
|
|
132
|
-
client = Client(base_url=url, headers=headers_dict)
|
|
123
|
+
client = Client(base_url=url, headers=headers_dict, verify=not no_verify)
|
|
133
124
|
|
|
134
125
|
resource_models, resource_types_obj, spc_obj = load_config_files(
|
|
135
126
|
schemas, resource_types, service_provider_config
|