diff --git a/examples/client.py b/examples/client.py index 6f09d14..5123b5b 100644 --- a/examples/client.py +++ b/examples/client.py @@ -20,13 +20,16 @@ class SiteAdminNameSpace(ClientNamespace): def on_connect(self): print(f"Connection to namespace {self.namespace} established") self.emit("list_provider_federation_requests", {"username": ""}) + self.emit("get_form") def on_connect_error(self, data): print(f"Failed to connect to namespace {self.namespace}", data) def on_list_provider_federation_requests(self, data): print(f"Message received with {data}") - self.disconnect() + + def on_get_form(self, data): + print(f"Message received with {data}") def on_disconnect(self): print(f"Disconnected from namespace {self.namespace}") @@ -41,4 +44,5 @@ def on_disconnect(self): transports=["websocket", "polling"], auth={"token": args.token}, ) -sio.wait() +sio.sleep(5) +sio.disconnect() \ No newline at end of file diff --git a/fed_mng/socketio/site_admin.py b/fed_mng/socketio/site_admin.py index ec17b4f..b1b12ad 100644 --- a/fed_mng/socketio/site_admin.py +++ b/fed_mng/socketio/site_admin.py @@ -1,5 +1,6 @@ from typing import Any, Literal +import requests from socketio import AsyncNamespace from fed_mng.socketio.utils import validate_auth_on_connect @@ -75,3 +76,46 @@ async def on_delete_federated_provider(self, sid, data): """ print("Received data ", data) # TODO: Start a new workflow instance to delete a provider + + async def on_get_form(self, id): + """Send a dict with the details to use to submit a new provider request.""" + resp = requests.get( + "https://raw.githubusercontent.com/infn-datacloud/federation-registry-feeder/main/json-config-schemas/provider-config-schema.json" + ) + idp_data = self._resolve_defs( + resp.json()["properties"].pop("trusted_idps"), resp.json()["$defs"] + ) + print("Identity provider section: %r" % idp_data) + provider_data = self._resolve_defs( + resp.json()["properties"]["openstack"], resp.json()["$defs"] + ) + print("Provider section: %r" % provider_data) + await self.emit("get_form", {"idp": idp_data, "provider": provider_data}) + + def _resolve_defs( + self, data: dict[str, Any], definitions: dict[str, dict] + ) -> dict[str, dict]: + """Convert the json schema in a more suitable dict. + + Expand $ref keys with the corresponding definitions. + Move the required key inside the corresponding dict. + + Return the resolved dict. + """ + resolved_data = {} + + # Expand references + for key, value in data.items(): + if isinstance(value, dict): + value = definitions.get(key) if value.get("$ref", None) else value + resolved_data[key] = self._resolve_defs(value, definitions) + else: + resolved_data[key] = value + + # Add required flag to target item + required_keys = resolved_data.pop("required", None) + if required_keys is not None and isinstance(required_keys, list): + for k in required_keys: + resolved_data["properties"][k]["required"] = True + + return resolved_data