|
5 | 5 | from httpx2 import Client |
6 | 6 | from scim2_client.engines.httpx2 import SyncSCIMClient |
7 | 7 | from scim2_models import ListResponse |
8 | | -from scim2_models import Resource |
9 | 8 | from scim2_models import ResourceType |
10 | 9 | from scim2_models import Schema |
| 10 | +from scim2_models import ScimProvider |
| 11 | +from scim2_models import ScimProviderError |
11 | 12 | from scim2_models import ServiceProviderConfig |
12 | 13 | from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter |
13 | 14 |
|
|
25 | 26 | from scim2_cli.utils import split_headers |
26 | 27 |
|
27 | 28 |
|
28 | | -def load_config_files( |
29 | | - schemas_fd, resource_types_fd, service_provider_config_fd |
30 | | -) -> tuple[ |
31 | | - list[type[Resource]] | None, |
32 | | - list[ResourceType] | None, |
33 | | - ServiceProviderConfig | None, |
34 | | -]: |
35 | | - if schemas_fd: |
36 | | - schemas_payload = json.load(schemas_fd) |
37 | | - if isinstance(schemas_payload, dict): |
38 | | - schemas_obj = ListResponse[Schema].model_validate(schemas_payload).resources |
39 | | - else: |
40 | | - schemas_obj = [Schema.model_validate(schema) for schema in schemas_payload] |
41 | | - resource_models = [Resource.from_schema(schema) for schema in schemas_obj] |
42 | | - |
43 | | - else: |
44 | | - resource_models = None |
45 | | - |
46 | | - if resource_types_fd: |
47 | | - resource_types_payload = json.load(resource_types_fd) |
48 | | - if isinstance(schemas_payload, dict): |
49 | | - resource_types = ( |
50 | | - ListResponse[ResourceType] |
51 | | - .model_validate(resource_types_payload) |
52 | | - .resources |
53 | | - ) |
54 | | - else: |
55 | | - resource_types = [ |
56 | | - ResourceType.model_validate(item) for item in resource_types_payload |
57 | | - ] |
58 | | - else: |
59 | | - resource_types = None |
60 | | - |
61 | | - if service_provider_config_fd: |
62 | | - spc_payload = json.load(service_provider_config_fd) |
63 | | - service_provider_config = ServiceProviderConfig.model_validate(spc_payload) |
64 | | - else: |
65 | | - service_provider_config = None |
66 | | - |
67 | | - return resource_models, resource_types, service_provider_config |
| 29 | +def load_objects(fd, model): |
| 30 | + """Read a list of objects, bare or wrapped in a ListResponse, from a JSON file.""" |
| 31 | + payload = json.load(fd) |
| 32 | + if isinstance(payload, dict): |
| 33 | + return ListResponse[model].model_validate(payload).resources or [] |
| 34 | + return [model.model_validate(item) for item in payload] |
| 35 | + |
| 36 | + |
| 37 | +def describe_server( |
| 38 | + scim_client, schemas_fd, resource_types_fd, service_provider_config_fd |
| 39 | +) -> ScimProvider: |
| 40 | + """Describe the server with the configuration files, and query it for the others.""" |
| 41 | + resource_types = ( |
| 42 | + load_objects(resource_types_fd, ResourceType) |
| 43 | + if resource_types_fd |
| 44 | + else scim_client.query(ResourceType).resources or [] |
| 45 | + ) |
| 46 | + schemas = ( |
| 47 | + load_objects(schemas_fd, Schema) |
| 48 | + if schemas_fd |
| 49 | + else scim_client.query(Schema).resources or [] |
| 50 | + ) |
| 51 | + config = ( |
| 52 | + ServiceProviderConfig.model_validate(json.load(service_provider_config_fd)) |
| 53 | + if service_provider_config_fd |
| 54 | + else scim_client.query(ServiceProviderConfig) |
| 55 | + ) |
| 56 | + return ScimProvider.from_discovery(schemas, resource_types, config) |
68 | 57 |
|
69 | 58 |
|
70 | 59 | @click.group(cls=make_rst_to_ansi_formatter(DOC_URL, group=True)) |
@@ -123,31 +112,21 @@ def cli( |
123 | 112 | headers_dict = split_headers(header) |
124 | 113 | client = Client(base_url=url, headers=headers_dict, verify=not no_verify) |
125 | 114 |
|
126 | | - resource_models, resource_types_obj, spc_obj = load_config_files( |
127 | | - schemas, resource_types, service_provider_config |
128 | | - ) |
129 | | - |
130 | | - scim_client = SyncSCIMClient( |
131 | | - client, |
132 | | - resource_models=resource_models, |
133 | | - resource_types=resource_types_obj, |
134 | | - service_provider_config=spc_obj, |
135 | | - ) |
| 115 | + scim_client = SyncSCIMClient(client) |
136 | 116 | try: |
137 | | - scim_client.discover( |
138 | | - schemas=not bool(schemas), |
139 | | - resource_types=not bool(resource_types), |
140 | | - service_provider_config=not bool(service_provider_config), |
| 117 | + scim_client.provider = describe_server( |
| 118 | + scim_client, schemas, resource_types, service_provider_config |
141 | 119 | ) |
142 | | - except SCIM_EXCEPTIONS as exc: |
| 120 | + except (*SCIM_EXCEPTIONS, ScimProviderError) as exc: |
143 | 121 | raise exception_to_click_error(exc) from exc |
144 | 122 |
|
| 123 | + provider = scim_client.provider |
145 | 124 | ctx.obj["client"] = scim_client |
146 | 125 | ctx.obj["resource_models"] = { |
147 | 126 | escape_control_characters( |
148 | 127 | re.sub(r"\[.*\]", "", resource_model.__name__.lower()) |
149 | 128 | ): resource_model |
150 | | - for resource_model in ctx.obj["client"].resource_models |
| 129 | + for resource_model in map(provider.model_for, provider.resource_types) |
151 | 130 | } |
152 | 131 |
|
153 | 132 | if not click.get_text_stream("stdin").isatty(): # pragma: no cover |
|
0 commit comments