scim2-cli 0.1.0__tar.gz → 0.1.1__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.
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.1
2
+ Name: scim2-cli
3
+ Version: 0.1.1
4
+ Summary: SCIM application development CLI
5
+ License: MIT
6
+ Keywords: scim,scim2,provisioning
7
+ Author: Yaal Coop
8
+ Author-email: contact@yaal.coop
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Requires-Dist: click (>=8.1.7,<9.0.0)
23
+ Requires-Dist: scim2-client (>=0.1.4,<0.2.0)
24
+ Requires-Dist: sphinx-click-rst-to-ansi-formatter (>=0.1.0,<0.2.0)
25
+ Description-Content-Type: text/markdown
26
+
27
+ # scim2-cli
28
+
29
+ An utility command line to help you perform requests against a SCIM server, while validating input and response payloads.
30
+
31
+ ## Installation
32
+
33
+ ```shell
34
+ pip install scim2-cli
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ Check the [reference](https://scim2-cli.readthedocs.io/en/latest/reference.html) for more details.
40
+
41
+ Here is an example of resource creation:
42
+
43
+ ```shell
44
+ $ scim2 https://auth.example create user << EOL
45
+ {
46
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
47
+ "userName": "bjensen@example.com"
48
+ }
49
+ EOL
50
+ {
51
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
52
+ "id": "2819c223-7f76-453a-919d-413861904646",
53
+ "userName": "bjensen@example.com",
54
+ "meta": {
55
+ "resourceType": "User",
56
+ "created": "2010-01-23T04:56:22Z",
57
+ "lastModified": "2011-05-13T04:42:34Z",
58
+ "version": 'W\\/"3694e05e9dff590"',
59
+ "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
60
+ },
61
+ }
62
+ ```
63
+
64
+ Here is an example of resource query:
65
+
66
+ ```shell
67
+ $ scim2 https://auth.example query user 2819c223-7f76-453a-919d-413861904646
68
+ {
69
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
70
+ "id": "2819c223-7f76-453a-919d-413861904646",
71
+ "userName": "bjensen@example.com",
72
+ "meta": {
73
+ "resourceType": "User",
74
+ "created": "2010-01-23T04:56:22Z",
75
+ "lastModified": "2011-05-13T04:42:34Z",
76
+ "version": 'W\\/"3694e05e9dff590"',
77
+ "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
78
+ }
79
+ }
80
+ ```
81
+
@@ -0,0 +1,54 @@
1
+ # scim2-cli
2
+
3
+ An utility command line to help you perform requests against a SCIM server, while validating input and response payloads.
4
+
5
+ ## Installation
6
+
7
+ ```shell
8
+ pip install scim2-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Check the [reference](https://scim2-cli.readthedocs.io/en/latest/reference.html) for more details.
14
+
15
+ Here is an example of resource creation:
16
+
17
+ ```shell
18
+ $ scim2 https://auth.example create user << EOL
19
+ {
20
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
21
+ "userName": "bjensen@example.com"
22
+ }
23
+ EOL
24
+ {
25
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
26
+ "id": "2819c223-7f76-453a-919d-413861904646",
27
+ "userName": "bjensen@example.com",
28
+ "meta": {
29
+ "resourceType": "User",
30
+ "created": "2010-01-23T04:56:22Z",
31
+ "lastModified": "2011-05-13T04:42:34Z",
32
+ "version": 'W\\/"3694e05e9dff590"',
33
+ "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
34
+ },
35
+ }
36
+ ```
37
+
38
+ Here is an example of resource query:
39
+
40
+ ```shell
41
+ $ scim2 https://auth.example query user 2819c223-7f76-453a-919d-413861904646
42
+ {
43
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
44
+ "id": "2819c223-7f76-453a-919d-413861904646",
45
+ "userName": "bjensen@example.com",
46
+ "meta": {
47
+ "resourceType": "User",
48
+ "created": "2010-01-23T04:56:22Z",
49
+ "lastModified": "2011-05-13T04:42:34Z",
50
+ "version": 'W\\/"3694e05e9dff590"',
51
+ "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
52
+ }
53
+ }
54
+ ```
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "scim2-cli"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "SCIM application development CLI"
9
9
  authors = ["Yaal Coop <contact@yaal.coop>"]
10
10
  license = "MIT"
@@ -27,7 +27,7 @@ classifiers = [
27
27
  [tool.poetry.dependencies]
28
28
  python = "^3.10"
29
29
  click = "^8.1.7"
30
- requests = "^2.32.2"
30
+ scim2-client = "^0.1.4"
31
31
  sphinx-click-rst-to-ansi-formatter = "^0.1.0"
32
32
 
33
33
  [tool.poetry.group.doc]
@@ -0,0 +1,49 @@
1
+ import json
2
+
3
+ import click
4
+ from httpx import Client
5
+ from scim2_client import SCIMClient
6
+ from scim2_models import EnterpriseUser
7
+ from scim2_models import Group
8
+ from scim2_models import User
9
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
10
+
11
+ from .create import create_cli
12
+ from .delete import delete_cli
13
+ from .query import query_cli
14
+ from .replace import replace_cli
15
+ from .search import search_cli
16
+ from .utils import DOC_URL
17
+
18
+
19
+ @click.group(cls=make_rst_to_ansi_formatter(DOC_URL, group=True))
20
+ @click.argument("url")
21
+ @click.pass_context
22
+ def cli(ctx, url):
23
+ """SCIM application development CLI."""
24
+
25
+ ctx.ensure_object(dict)
26
+ ctx.obj["URL"] = url
27
+ client = Client(base_url=ctx.obj["URL"])
28
+ ctx.obj["client"] = SCIMClient(
29
+ client, resource_types=(User, User[EnterpriseUser], Group)
30
+ )
31
+ ctx.obj["resource_types"] = {
32
+ resource_type.__name__.lower(): resource_type
33
+ for resource_type in ctx.obj["client"].resource_types
34
+ }
35
+
36
+ if not click.get_text_stream("stdin").isatty(): # pragma: no cover
37
+ if stdin := click.get_text_stream("stdin").read().strip():
38
+ try:
39
+ ctx.obj["stdin"] = json.loads(stdin)
40
+ except json.JSONDecodeError as exc:
41
+ message = f"Invalid JSON input.\n{exc}"
42
+ raise click.ClickException(message) from exc
43
+
44
+
45
+ cli.add_command(create_cli)
46
+ cli.add_command(query_cli)
47
+ cli.add_command(replace_cli)
48
+ cli.add_command(delete_cli)
49
+ cli.add_command(search_cli)
@@ -0,0 +1,48 @@
1
+ import click
2
+ import httpx
3
+ from click import ClickException
4
+ from pydantic import ValidationError
5
+ from scim2_client import SCIMClientError
6
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
7
+
8
+ from .utils import DOC_URL
9
+ from .utils import formatted_payload
10
+
11
+
12
+ @click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="create")
13
+ @click.pass_context
14
+ @click.option(
15
+ "--indent/--no-indent",
16
+ is_flag=True,
17
+ default=True,
18
+ help="Indent JSON response payloads.",
19
+ )
20
+ def create_cli(ctx, indent):
21
+ """Perform a `SCIM POST <https://www.rfc-editor.org/rfc/rfc7644#section-3.3>`_ request
22
+ on resources endpoint.
23
+
24
+ Input data is expected to be passed in JSON format to stdin:
25
+
26
+ .. code-block:: bash
27
+
28
+ echo '{"userName": "bjensen@example.com", "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"]}' | scim https://scim.example create user
29
+
30
+ """
31
+
32
+ payload = ctx.obj.get("stdin")
33
+ if not payload:
34
+ raise ClickException("Input data is missing")
35
+
36
+ try:
37
+ response = ctx.obj["client"].create(payload)
38
+
39
+ except (httpx.HTTPError, SCIMClientError) as exc:
40
+ raise ClickException(exc) from exc
41
+
42
+ except ValidationError as exc:
43
+ payload = formatted_payload(exc.response_payload, indent)
44
+ message = f"The server response is invalid:\n{payload}\n{exc}"
45
+ raise ClickException(message) from exc
46
+
47
+ payload = formatted_payload(response.model_dump(), indent)
48
+ click.echo(payload)
@@ -0,0 +1,45 @@
1
+ import click
2
+ import httpx
3
+ from click import ClickException
4
+ from scim2_client import SCIMClientError
5
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
6
+
7
+ from .utils import DOC_URL
8
+ from .utils import formatted_payload
9
+
10
+
11
+ @click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="delete")
12
+ @click.argument("resource-type", required=True)
13
+ @click.argument("id", required=True)
14
+ @click.option(
15
+ "--indent/--no-indent",
16
+ is_flag=True,
17
+ default=True,
18
+ help="Indent JSON response payloads.",
19
+ )
20
+ @click.pass_context
21
+ def delete_cli(ctx, resource_type, id, indent):
22
+ """Perform a `SCIM DELETE query <https://www.rfc-editor.org/rfc/rfc7644#section-3.6>`_ request.
23
+
24
+ .. code-block:: bash
25
+
26
+ scim https://scim.example delete user 1234
27
+ """
28
+
29
+ try:
30
+ resource_type = ctx.obj["resource_types"][resource_type]
31
+ except KeyError:
32
+ ok_values = ", ".join(ctx.obj["resource_types"])
33
+ raise ClickException(
34
+ f"Unknown resource type '{resource_type}'. Available values are: {ok_values}'"
35
+ )
36
+
37
+ try:
38
+ response = ctx.obj["client"].delete(resource_type, id)
39
+
40
+ except (httpx.HTTPError, SCIMClientError) as exc:
41
+ raise ClickException(exc) from exc
42
+
43
+ if response:
44
+ payload = formatted_payload(response.model_dump(), indent)
45
+ click.echo(payload)
@@ -0,0 +1,132 @@
1
+ from typing import List
2
+ from typing import Optional
3
+
4
+ import click
5
+ import httpx
6
+ from click import ClickException
7
+ from pydantic import ValidationError
8
+ from scim2_client import SCIMClientError
9
+ from scim2_models import SearchRequest
10
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
11
+
12
+ from .utils import DOC_URL
13
+ from .utils import formatted_payload
14
+
15
+
16
+ @click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="query")
17
+ @click.pass_context
18
+ @click.argument("resource_type", required=False)
19
+ @click.argument("id", required=False)
20
+ @click.option(
21
+ "--attribute",
22
+ multiple=True,
23
+ help="A multi-valued list of strings indicating the names of resource attributes to return in the response, overriding the set of attributes that would be returned by default.",
24
+ )
25
+ @click.option(
26
+ "--excluded-attribute",
27
+ multiple=True,
28
+ help="A multi-valued list of strings indicating the names of resource attributes to be removed from the default set of attributes to return.",
29
+ )
30
+ @click.option(
31
+ "--start-index",
32
+ type=int,
33
+ help="An integer indicating the 1-based index of the first query result.",
34
+ )
35
+ @click.option(
36
+ "--count",
37
+ type=int,
38
+ help="An integer indicating the desired maximum number of query results per page.",
39
+ )
40
+ @click.option(
41
+ "--filter", help="The filter string used to request a subset of resources."
42
+ )
43
+ @click.option(
44
+ "--sort-by",
45
+ help="A string indicating the attribute whose value SHALL be used to order the returned responses.",
46
+ )
47
+ @click.option(
48
+ "--sort-order",
49
+ help="A string indicating the order in which the “sortBy” parameter is applied.",
50
+ )
51
+ @click.option(
52
+ "--indent/--no-indent",
53
+ is_flag=True,
54
+ default=True,
55
+ help="Indent JSON response payloads.",
56
+ )
57
+ def query_cli(
58
+ ctx,
59
+ resource_type: Optional[str],
60
+ id: Optional[str],
61
+ attribute: List[str],
62
+ excluded_attribute: List[str],
63
+ start_index: int,
64
+ count: int,
65
+ filter: str,
66
+ sort_by: str,
67
+ sort_order: str,
68
+ indent: bool,
69
+ ):
70
+ """Perform a `SCIM GET <https://www.rfc-editor.org/rfc/rfc7644#section-3.4.1>`_ request
71
+ on the :code:`RESOURCE_TYPE` endpoint.
72
+
73
+ - If :code:`RESOURCE_TYPE` is :code:`user` and :code:`id` is `1234`, then the request will made on the :code:`/Users/1234` endpoint.
74
+ - If :code:`RESOURCE_TYPE` is :code:`user` and :code:`id` is not set, then the request will made on the :code:`/Users` endpoint.
75
+ - If :code:`RESOURCE_TYPE` is not set, then the request will made on the :code:`/` endpoint.
76
+
77
+ Data passed in JSON format to stdin is sent as request arguments and all the other query arguments are ignored:
78
+
79
+ .. code-block:: bash
80
+
81
+ echo '{"startIndex": 50, "count": 10}' | scim https://scim.example query user
82
+ """
83
+
84
+ if resource_type:
85
+ try:
86
+ resource_type = ctx.obj["resource_types"][resource_type]
87
+ except KeyError:
88
+ ok_values = ", ".join(ctx.obj["resource_types"])
89
+ raise ClickException(
90
+ f"Unknown resource type '{resource_type}. Available values are: {ok_values}'"
91
+ )
92
+
93
+ if ctx.obj.get("stdin"):
94
+ check_request_payload = False
95
+ payload = ctx.obj.get("stdin")
96
+
97
+ else:
98
+ check_request_payload = True
99
+ payload = SearchRequest(
100
+ attributes=attribute,
101
+ excluded_attributes=excluded_attribute,
102
+ start_index=start_index,
103
+ count=count,
104
+ filter=filter,
105
+ sort_by=sort_by,
106
+ sort_order=sort_order,
107
+ )
108
+
109
+ try:
110
+ if resource_type:
111
+ response = ctx.obj["client"].query(
112
+ resource_type,
113
+ id,
114
+ search_request=payload,
115
+ check_request_payload=check_request_payload,
116
+ )
117
+
118
+ else:
119
+ response = ctx.obj["client"].query_all(
120
+ search_request=payload, check_request_payload=check_request_payload
121
+ )
122
+
123
+ except (httpx.HTTPError, SCIMClientError) as exc:
124
+ raise ClickException(exc) from exc
125
+
126
+ except ValidationError as exc:
127
+ payload = formatted_payload(exc.response_payload, indent)
128
+ message = f"The server response is invalid:\n{payload}\n{exc}"
129
+ raise ClickException(message) from exc
130
+
131
+ payload = formatted_payload(response.model_dump(), indent)
132
+ click.echo(payload)
@@ -0,0 +1,48 @@
1
+ import click
2
+ import httpx
3
+ from click import ClickException
4
+ from pydantic import ValidationError
5
+ from scim2_client import SCIMClientError
6
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
7
+
8
+ from .utils import DOC_URL
9
+ from .utils import formatted_payload
10
+
11
+
12
+ @click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="replace")
13
+ @click.pass_context
14
+ @click.option(
15
+ "--indent/--no-indent",
16
+ is_flag=True,
17
+ default=True,
18
+ help="Indent JSON response payloads.",
19
+ )
20
+ def replace_cli(ctx, indent):
21
+ """Perform a `SCIM PUT <https://www.rfc-editor.org/rfc/rfc7644#section-3.5.1>`_ request
22
+ on the resources endpoint.
23
+
24
+ Input data is expected to be passed in JSON format to stdin:
25
+
26
+ .. code-block:: bash
27
+
28
+ echo '{"userName": "bjensen@example.com", "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "id": "1234"}' | scim https://scim.example replace user
29
+
30
+ """
31
+
32
+ payload = ctx.obj.get("stdin")
33
+ if not payload:
34
+ raise ClickException("Input data is missing")
35
+
36
+ try:
37
+ response = ctx.obj["client"].replace(payload)
38
+
39
+ except (httpx.HTTPError, SCIMClientError) as exc:
40
+ raise ClickException(exc) from exc
41
+
42
+ except ValidationError as exc:
43
+ payload = formatted_payload(exc.response_payload, indent)
44
+ message = f"The server response is invalid:\n{payload}\n{exc}"
45
+ raise ClickException(message) from exc
46
+
47
+ payload = formatted_payload(response.model_dump(), indent)
48
+ click.echo(payload)
@@ -0,0 +1,106 @@
1
+ from typing import List
2
+
3
+ import click
4
+ import httpx
5
+ from click import ClickException
6
+ from pydantic import ValidationError
7
+ from scim2_client import SCIMClientError
8
+ from scim2_models import SearchRequest
9
+ from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
10
+
11
+ from .utils import DOC_URL
12
+ from .utils import formatted_payload
13
+
14
+
15
+ @click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="search")
16
+ @click.pass_context
17
+ @click.option(
18
+ "--attribute",
19
+ multiple=True,
20
+ help="A multi-valued list of strings indicating the names of resource attributes to return in the response, overriding the set of attributes that would be returned by default.",
21
+ )
22
+ @click.option(
23
+ "--excluded-attribute",
24
+ multiple=True,
25
+ help="A multi-valued list of strings indicating the names of resource attributes to be removed from the default set of attributes to return.",
26
+ )
27
+ @click.option(
28
+ "--start-index",
29
+ type=int,
30
+ help="An integer indicating the 1-based index of the first query result.",
31
+ )
32
+ @click.option(
33
+ "--count",
34
+ type=int,
35
+ help="An integer indicating the desired maximum number of query results per page.",
36
+ )
37
+ @click.option(
38
+ "--filter", help="The filter string used to request a subset of resources."
39
+ )
40
+ @click.option(
41
+ "--sort-by",
42
+ help="A string indicating the attribute whose value SHALL be used to order the returned responses.",
43
+ )
44
+ @click.option(
45
+ "--sort-order",
46
+ help="A string indicating the order in which the “sortBy” parameter is applied.",
47
+ )
48
+ @click.option(
49
+ "--indent/--no-indent",
50
+ is_flag=True,
51
+ default=True,
52
+ help="Indent JSON response payloads.",
53
+ )
54
+ def search_cli(
55
+ ctx,
56
+ attribute: List[str],
57
+ excluded_attribute: List[str],
58
+ start_index: int,
59
+ count: int,
60
+ filter: str,
61
+ sort_by: str,
62
+ sort_order: str,
63
+ indent: bool,
64
+ ):
65
+ """Perform a `SCIM GET <https://www.rfc-editor.org/rfc/rfc7644#section-3.4.1>`_ request
66
+ on the :code:`/.search` endpoint.
67
+
68
+ Data passed in JSON format to stdin is sent as request arguments and all the other query arguments are ignored:
69
+
70
+ .. code-block:: bash
71
+
72
+ echo '{"startIndex": 50, "count": 10}' | scim https://scim.example search user
73
+ """
74
+
75
+ if ctx.obj.get("stdin"):
76
+ check_request_payload = False
77
+ payload = ctx.obj.get("stdin")
78
+
79
+ else:
80
+ check_request_payload = True
81
+ payload = SearchRequest(
82
+ attributes=attribute,
83
+ excluded_attributes=excluded_attribute,
84
+ start_index=start_index,
85
+ count=count,
86
+ filter=filter,
87
+ sort_by=sort_by,
88
+ sort_order=sort_order,
89
+ )
90
+
91
+ try:
92
+ response = ctx.obj["client"].search(
93
+ search_request=payload,
94
+ check_request_payload=check_request_payload,
95
+ )
96
+
97
+ except (httpx.HTTPError, SCIMClientError) as exc:
98
+ raise ClickException(exc) from exc
99
+
100
+ except ValidationError as exc:
101
+ payload = formatted_payload(exc.response_payload, indent)
102
+ message = f"The server response is invalid:\n{payload}\n{exc}"
103
+ raise ClickException(message) from exc
104
+
105
+ payload = formatted_payload(response.model_dump(), indent)
106
+ click.echo(payload)
@@ -0,0 +1,9 @@
1
+ import json
2
+
3
+ DOC_URL = "https://scim2-cli.readthedocs.io/"
4
+ INDENTATION_SIZE = 4
5
+
6
+
7
+ def formatted_payload(obj, indent):
8
+ indent = INDENTATION_SIZE if indent else False
9
+ return json.dumps(obj, indent=indent)
scim2_cli-0.1.0/PKG-INFO DELETED
@@ -1,30 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: scim2-cli
3
- Version: 0.1.0
4
- Summary: SCIM application development CLI
5
- License: MIT
6
- Keywords: scim,scim2,provisioning
7
- Author: Yaal Coop
8
- Author-email: contact@yaal.coop
9
- Requires-Python: >=3.10,<4.0
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Environment :: Web Environment
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Programming Language :: Python :: 3.9
21
- Classifier: Programming Language :: Python :: Implementation :: CPython
22
- Requires-Dist: click (>=8.1.7,<9.0.0)
23
- Requires-Dist: requests (>=2.32.2,<3.0.0)
24
- Requires-Dist: sphinx-click-rst-to-ansi-formatter (>=0.1.0,<0.2.0)
25
- Description-Content-Type: text/markdown
26
-
27
- # scim2-cli
28
-
29
- A scim utility command line.
30
-
scim2_cli-0.1.0/README.md DELETED
@@ -1,3 +0,0 @@
1
- # scim2-cli
2
-
3
- A scim utility command line.
@@ -1,129 +0,0 @@
1
- import json
2
-
3
- import click
4
- import requests
5
- from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
6
-
7
- DOC_URL = "https://scim2-cli.readthedocs.io/"
8
- BASE_HEADERS = {
9
- "Accept": "application/scim+json",
10
- "Content-Type": "application/scim+json",
11
- }
12
-
13
-
14
- @click.group(cls=make_rst_to_ansi_formatter(DOC_URL, group=True))
15
- @click.argument("url")
16
- @click.pass_context
17
- def cli(ctx, url):
18
- """SCIM application development CLI."""
19
- ctx.ensure_object(dict)
20
- ctx.obj["URL"] = url
21
-
22
- if not click.get_text_stream("stdin").isatty(): # pragma: no cover
23
- stdin = click.get_text_stream("stdin").read().strip()
24
- ctx.obj["STDIN"] = json.loads(stdin)
25
-
26
-
27
- @cli.command(cls=make_rst_to_ansi_formatter(DOC_URL))
28
- @click.pass_context
29
- def get(ctx):
30
- """Perform a `SCIM GET <https://www.rfc-editor.org/rfc/rfc7644#section-3.4.1>`_ request.
31
-
32
- Data passed in JSON format to stdin is sent as request arguments:
33
-
34
- .. code-block:: bash
35
-
36
- echo '{"foo": "bar"}' | scim https://scim.example get
37
- """
38
-
39
- response = requests.get(
40
- ctx.obj["URL"],
41
- params=ctx.obj.get("STDIN"),
42
- headers=BASE_HEADERS,
43
- allow_redirects=True,
44
- )
45
- click.echo(response.text)
46
-
47
-
48
- @cli.command(cls=make_rst_to_ansi_formatter(DOC_URL))
49
- @click.pass_context
50
- def post(ctx):
51
- """Perform a `SCIM POST <https://www.rfc-editor.org/rfc/rfc7644#section-3.3>`_ request.
52
-
53
- Data passed in JSON format to stdin is sent as request payload:
54
-
55
- .. code-block:: bash
56
-
57
- echo '{"foo": "bar"}' | scim https://scim.example post
58
- """
59
-
60
- response = requests.post(
61
- ctx.obj["URL"],
62
- json=ctx.obj.get("STDIN"),
63
- headers=BASE_HEADERS,
64
- allow_redirects=True,
65
- )
66
- click.echo(response.text)
67
-
68
-
69
- @cli.command(cls=make_rst_to_ansi_formatter(DOC_URL))
70
- @click.pass_context
71
- def put(ctx):
72
- """Perform a `SCIM PUT <https://www.rfc-editor.org/rfc/rfc7644#section-3.5.1>`_ request.
73
-
74
- Data passed in JSON format to stdin is sent as request payload:
75
-
76
- .. code-block:: bash
77
-
78
- echo '{"foo": "bar"}' | scim https://scim.example put
79
- """
80
-
81
- response = requests.put(
82
- ctx.obj["URL"],
83
- json=ctx.obj.get("STDIN"),
84
- headers=BASE_HEADERS,
85
- allow_redirects=True,
86
- )
87
- click.echo(response.text)
88
-
89
-
90
- @cli.command(cls=make_rst_to_ansi_formatter(DOC_URL))
91
- @click.pass_context
92
- def patch(ctx):
93
- """Perform a `SCIM PATCH <https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2>`_ request.
94
-
95
- Data passed in JSON format to stdin is sent as request payload:
96
-
97
- .. code-block:: bash
98
-
99
- echo '{"foo": "bar"}' | scim https://scim.example patch
100
- """
101
-
102
- response = requests.patch(
103
- ctx.obj["URL"],
104
- json=ctx.obj.get("STDIN"),
105
- headers=BASE_HEADERS,
106
- allow_redirects=True,
107
- )
108
- click.echo(response.text)
109
-
110
-
111
- @cli.command(cls=make_rst_to_ansi_formatter(DOC_URL))
112
- @click.pass_context
113
- def delete(ctx):
114
- """Perform a `SCIM DELETE <https://www.rfc-editor.org/rfc/rfc7644#section-3.6>`_ request.
115
-
116
- Data passed in JSON format to stdin is sent as request payload:
117
-
118
- .. code-block:: bash
119
-
120
- echo '{"foo": "bar"}' | scim https://scim.example delete
121
- """
122
-
123
- response = requests.delete(
124
- ctx.obj["URL"],
125
- json=ctx.obj.get("STDIN"),
126
- headers=BASE_HEADERS,
127
- allow_redirects=True,
128
- )
129
- click.echo(response.text)