Skip to content

Commit c1474f5

Browse files
committed
refactor: --headers is a top-level option
1 parent 709b99e commit c1474f5

File tree

8 files changed

+67
-58
lines changed

8 files changed

+67
-58
lines changed

scim2_cli/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
from scim2_cli.test import test_cli
1919
from scim2_cli.utils import DOC_URL
2020

21+
from .utils import split_headers
22+
2123

2224
# monkeypatching pydanclick until this patch is released
2325
# https://github.com/felix-martel/pydanclick/pull/25
@@ -39,12 +41,15 @@ def _is_pydantic_model(model: Any) -> TypeGuard[type[BaseModel]]:
3941

4042
@click.group(cls=make_rst_to_ansi_formatter(DOC_URL, group=True))
4143
@click.option("--url", help="The SCIM server endpoint.")
44+
@click.option(
45+
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
46+
)
4247
@click.pass_context
43-
def cli(ctx, url: str):
48+
def cli(ctx, url: str, headers: list[str]):
4449
"""SCIM application development CLI."""
4550
ctx.ensure_object(dict)
4651
ctx.obj["URL"] = url
47-
client = Client(base_url=ctx.obj["URL"])
52+
client = Client(base_url=ctx.obj["URL"], headers=split_headers(headers))
4853
ctx.obj["client"] = SyncSCIMClient(client, resource_models=(User, Group))
4954
ctx.obj["client"].register_naive_resource_types()
5055
ctx.obj["resource_models"] = {

scim2_cli/create.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@
1010
from .utils import DOC_URL
1111
from .utils import ModelCommand
1212
from .utils import formatted_payload
13-
from .utils import split_headers
1413
from .utils import unacceptable_fields
1514

1615

17-
def create_payload(client, payload, indent, headers):
16+
def create_payload(client, payload, indent):
1817
try:
19-
response = client.create(
20-
payload, headers=split_headers(headers), raise_scim_errors=False
21-
)
18+
response = client.create(payload, raise_scim_errors=False)
2219

2320
except SCIMClientError as scim_exc:
2421
message = str(scim_exc)
@@ -46,12 +43,9 @@ def create_factory(model):
4643
default=True,
4744
help="Indent JSON response payloads.",
4845
)
49-
@click.option(
50-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
51-
)
5246
@from_pydantic("obj", model, exclude=exclude)
5347
@click.pass_context
54-
def create_command(ctx, indent, headers, obj: model, *args, **kwargs):
48+
def create_command(ctx, indent, obj: model, *args, **kwargs):
5549
r"""Perform a `SCIM POST <https://www.rfc-editor.org/rfc/rfc7644#section-3.3>`_ request on resources endpoint.
5650
5751
Input data can be passed through parameters like :code:`--external-id`.
@@ -83,7 +77,7 @@ def create_command(ctx, indent, headers, obj: model, *args, **kwargs):
8377
click.echo(ctx.get_help())
8478
ctx.exit(1)
8579

86-
create_payload(ctx.obj["client"], payload, indent, headers)
80+
create_payload(ctx.obj["client"], payload, indent)
8781

8882
return create_command
8983

@@ -101,10 +95,7 @@ def create_command(ctx, indent, headers, obj: model, *args, **kwargs):
10195
default=True,
10296
help="Indent JSON response payloads.",
10397
)
104-
@click.option(
105-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
106-
)
107-
def create_cli(ctx, indent, headers):
98+
def create_cli(ctx, indent):
10899
"""Perform a `SCIM POST <https://www.rfc-editor.org/rfc/rfc7644#section-3.3>`_ request on resources endpoint.
109100
110101
There are subcommands for all the available models, with dynamic attributes.
@@ -129,4 +120,4 @@ def create_cli(ctx, indent, headers):
129120
click.echo(ctx.get_help())
130121
ctx.exit(1)
131122

132-
create_payload(ctx.obj["client"], payload, indent, headers)
123+
create_payload(ctx.obj["client"], payload, indent)

scim2_cli/delete.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,19 @@
99

1010
from .utils import DOC_URL
1111
from .utils import formatted_payload
12-
from .utils import split_headers
1312

1413

1514
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="delete")
1615
@click.argument("resource-type", required=True)
1716
@click.argument("id", required=True)
18-
@click.option(
19-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
20-
)
2117
@click.option(
2218
"--indent/--no-indent",
2319
is_flag=True,
2420
default=True,
2521
help="Indent JSON response payloads.",
2622
)
2723
@click.pass_context
28-
def delete_cli(ctx, resource_type, id, headers, indent):
24+
def delete_cli(ctx, resource_type, id, indent):
2925
"""Perform a `SCIM DELETE query <https://www.rfc-editor.org/rfc/rfc7644#section-3.6>`_ request.
3026
3127
.. code-block:: bash
@@ -41,9 +37,7 @@ def delete_cli(ctx, resource_type, id, headers, indent):
4137
) from exc
4238

4339
try:
44-
response = ctx.obj["client"].delete(
45-
resource_model, id, headers=split_headers(headers), raise_scim_errors=False
46-
)
40+
response = ctx.obj["client"].delete(resource_model, id, raise_scim_errors=False)
4741

4842
except SCIMClientError as scim_exc:
4943
message = str(scim_exc)

scim2_cli/query.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from .utils import DOC_URL
1010
from .utils import formatted_payload
11-
from .utils import split_headers
1211

1312

1413
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="query")
@@ -46,9 +45,6 @@
4645
"--sort-order",
4746
help="A string indicating the order in which the “sortBy” parameter is applied.",
4847
)
49-
@click.option(
50-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
51-
)
5248
@click.option(
5349
"--indent/--no-indent",
5450
is_flag=True,
@@ -66,7 +62,6 @@ def query_cli(
6662
filter: str,
6763
sort_by: str,
6864
sort_order: str,
69-
headers: list[str],
7065
indent: bool,
7166
):
7267
"""Perform a `SCIM GET <https://www.rfc-editor.org/rfc/rfc7644#section-3.4.1>`_ request on the :code:`RESOURCE_TYPE` endpoint.
@@ -113,7 +108,6 @@ def query_cli(
113108
id,
114109
search_request=payload,
115110
check_request_payload=check_request_payload,
116-
headers=split_headers(headers),
117111
raise_scim_errors=False,
118112
)
119113

scim2_cli/replace.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@
1010
from .utils import DOC_URL
1111
from .utils import ModelCommand
1212
from .utils import formatted_payload
13-
from .utils import split_headers
1413
from .utils import unacceptable_fields
1514

1615

17-
def replace_payload(client, payload, indent, headers):
16+
def replace_payload(client, payload, indent):
1817
try:
19-
response = client.replace(
20-
payload, headers=split_headers(headers), raise_scim_errors=False
21-
)
18+
response = client.replace(payload, raise_scim_errors=False)
2219

2320
except SCIMClientError as scim_exc:
2421
message = str(scim_exc)
@@ -47,12 +44,9 @@ def replace_factory(model):
4744
default=True,
4845
help="Indent JSON response payloads.",
4946
)
50-
@click.option(
51-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
52-
)
5347
@from_pydantic("obj", model, exclude=exclude)
5448
@click.pass_context
55-
def replace_command(ctx, indent, headers, obj: model, *args, **kwargs):
49+
def replace_command(ctx, indent, obj: model, *args, **kwargs):
5650
r"""Perform a `SCIM PUT <https://www.rfc-editor.org/rfc/rfc7644#section-3.3>`_ request on resources endpoint.
5751
5852
Input data can be passed through parameters like :code:`--external-id`.
@@ -85,7 +79,11 @@ def replace_command(ctx, indent, headers, obj: model, *args, **kwargs):
8579
click.echo(ctx.get_help())
8680
ctx.exit(1)
8781

88-
replace_payload(ctx.obj["client"], payload, indent, headers)
82+
replace_payload(
83+
ctx.obj["client"],
84+
payload,
85+
indent,
86+
)
8987

9088
return replace_command
9189

@@ -97,16 +95,13 @@ def replace_command(ctx, indent, headers, obj: model, *args, **kwargs):
9795
invoke_without_command=True,
9896
)
9997
@click.pass_context
100-
@click.option(
101-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
102-
)
10398
@click.option(
10499
"--indent/--no-indent",
105100
is_flag=True,
106101
default=True,
107102
help="Indent JSON response payloads.",
108103
)
109-
def replace_cli(ctx, headers, indent):
104+
def replace_cli(ctx, indent):
110105
"""Perform a `SCIM PUT <https://www.rfc-editor.org/rfc/rfc7644#section-3.5.1>`_ request on the resources endpoint.
111106
112107
There are subcommands for all the available models, with dynamic attributes.
@@ -131,4 +126,8 @@ def replace_cli(ctx, headers, indent):
131126
click.echo(ctx.get_help())
132127
ctx.exit(1)
133128

134-
replace_payload(ctx.obj["client"], payload, indent, headers)
129+
replace_payload(
130+
ctx.obj["client"],
131+
payload,
132+
indent,
133+
)

scim2_cli/search.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from .utils import DOC_URL
1010
from .utils import formatted_payload
11-
from .utils import split_headers
1211

1312

1413
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="search")
@@ -44,9 +43,6 @@
4443
"--sort-order",
4544
help="A string indicating the order in which the “sortBy” parameter is applied.",
4645
)
47-
@click.option(
48-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
49-
)
5046
@click.option(
5147
"--indent/--no-indent",
5248
is_flag=True,
@@ -62,7 +58,6 @@ def search_cli(
6258
filter: str,
6359
sort_by: str,
6460
sort_order: str,
65-
headers: list[str],
6661
indent: bool,
6762
):
6863
"""Perform a `SCIM GET <https://www.rfc-editor.org/rfc/rfc7644#section-3.4.1>`_ request on the :code:`/.search` endpoint.
@@ -94,7 +89,6 @@ def search_cli(
9489
response = ctx.obj["client"].search(
9590
search_request=payload,
9691
check_request_payload=check_request_payload,
97-
headers=split_headers(headers),
9892
raise_scim_errors=False,
9993
)
10094

scim2_cli/test.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,19 @@
55

66
from .utils import DOC_URL
77
from .utils import Color
8-
from .utils import split_headers
98

109

1110
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="test")
1211
@click.pass_context
13-
@click.option(
14-
"-h", "--headers", multiple=True, help="Header to pass in the HTTP requests."
15-
)
1612
@click.option("-v", "--verbose", is_flag=True, help="Enables verbose mode")
17-
def test_cli(ctx, headers, verbose):
13+
def test_cli(ctx, verbose):
1814
"""Perform a server SCIM compliance check using :doc:`scim2-tester <scim2-tester:index>`.
1915
2016
.. code-block:: bash
2117
2218
scim https://scim.example test
2319
"""
2420
client = ctx.obj["client"]
25-
client.client.headers.update(split_headers(headers))
2621
results = check_server(client)
2722
click.echo(f"Performing a SCIM compliance check on {client.client.base_url} ...")
2823
for result in results:

tests/test_cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,40 @@ def test_stdin_bad_json(runner, httpserver):
1616
)
1717
assert result.exit_code == 1
1818
assert "Invalid JSON input." in result.stdout
19+
20+
21+
def test_auth_headers(runner, httpserver, simple_user_payload):
22+
"""Test passing auth bearer headers."""
23+
httpserver.expect_request(
24+
"/Users/foobar", method="GET", headers={"Authorization": "Bearer token"}
25+
).respond_with_json(
26+
simple_user_payload("foobar"),
27+
status=200,
28+
content_type="application/scim+json",
29+
)
30+
31+
result = runner.invoke(
32+
cli,
33+
[
34+
"--url",
35+
httpserver.url_for("/"),
36+
"query",
37+
"user",
38+
"foobar",
39+
],
40+
)
41+
assert result.exit_code == 1
42+
43+
result = runner.invoke(
44+
cli,
45+
[
46+
"--url",
47+
httpserver.url_for("/"),
48+
"--headers",
49+
"Authorization: Bearer token",
50+
"query",
51+
"user",
52+
"foobar",
53+
],
54+
)
55+
assert result.exit_code == 0

0 commit comments

Comments
 (0)