trustgraph-base 2.4.3__tar.gz → 2.4.5__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.
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/PKG-INFO +1 -1
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/async_socket_client.py +51 -5
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/socket_client.py +48 -5
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/config_client.py +12 -0
- trustgraph_base-2.4.5/trustgraph/base/iam_client.py +279 -0
- trustgraph_base-2.4.5/trustgraph/base_version.py +1 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/__init__.py +9 -2
- trustgraph_base-2.4.5/trustgraph/messaging/translators/iam.py +194 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/__init__.py +1 -0
- trustgraph_base-2.4.5/trustgraph/schema/services/iam.py +142 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/PKG-INFO +1 -1
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/SOURCES.txt +3 -0
- trustgraph_base-2.4.3/trustgraph/base_version.py +0 -1
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/README.md +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/pyproject.toml +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/setup.cfg +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/api.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/async_bulk_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/async_flow.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/async_metrics.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/bulk_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/collection.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/config.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/exceptions.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/explainability.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/flow.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/knowledge.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/library.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/metrics.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/api/types.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/agent_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/agent_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/async_processor.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/backend.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/cassandra_config.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/chunking_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/collection_config_handler.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/consumer.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/consumer_spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/document_embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/document_embeddings_query_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/document_embeddings_store_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/dynamic_tool_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/embeddings_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/flow.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/flow_processor.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/graph_embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/graph_embeddings_query_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/graph_embeddings_store_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/graph_rag_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/kafka_backend.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/librarian_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/llm_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/logging.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/metrics.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/parameter_spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/processor_group.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/producer.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/producer_spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/prompt_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/publisher.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/pubsub.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/pulsar_backend.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/rabbitmq_backend.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/request_response_spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/row_embeddings_query_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/serialization.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/structured_query_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/subscriber.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/subscriber_spec.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/text_completion_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/tool_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/tool_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/tool_service_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/triples_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/triples_query_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/base/triples_store_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/agent_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/base.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/config_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/document_embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/document_rag_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/graph_embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/graph_rag_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/llm_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/prompt_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/row_embeddings_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/clients/triples_query_client.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/exceptions.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/ar.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/en.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/es.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/he.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/hi.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/pt.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/ru.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/sw.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/tr.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/i18n/packs/zh-cn.json +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/defs.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/document.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/identifier.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/organization.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/knowledge/publication.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/log_level.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/registry.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/agent.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/base.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/collection.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/config.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/diagnosis.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/document_loading.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/embeddings.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/embeddings_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/flow.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/knowledge.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/library.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/metadata.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/nlp_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/primitives.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/prompt.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/retrieval.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/rows_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/sparql_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/structured_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/text_completion.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/tool.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/messaging/translators/triples.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/objects/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/objects/field.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/objects/object.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/agent.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/namespaces.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/triples.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/uris.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/provenance/vocabulary.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/rdf.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/core/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/core/metadata.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/core/primitives.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/core/topic.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/__init__.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/document.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/embeddings.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/graph.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/knowledge.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/nlp.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/object.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/rows.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/knowledge/structured.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/agent.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/collection.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/config.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/diagnosis.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/flow.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/library.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/llm.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/lookup.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/nlp_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/prompt.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/retrieval.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/rows_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/sparql_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/storage.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/structured_query.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph/schema/services/tool_service.py +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/dependency_links.txt +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/entry_points.txt +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/requires.txt +0 -0
- {trustgraph_base-2.4.3 → trustgraph_base-2.4.5}/trustgraph_base.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trustgraph-base
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.5
|
|
4
4
|
Summary: TrustGraph provides a means to run a pipeline of flexible AI processing components in a flexible means to achieve a processing pipeline.
|
|
5
5
|
Author-email: "trustgraph.ai" <security@trustgraph.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/trustgraph-ai/trustgraph
|
|
@@ -49,21 +49,67 @@ class AsyncSocketClient:
|
|
|
49
49
|
return f"ws://{url}"
|
|
50
50
|
|
|
51
51
|
def _build_ws_url(self):
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
# /api/v1/socket uses the first-frame auth protocol — the
|
|
53
|
+
# token is sent as the first frame after connecting rather
|
|
54
|
+
# than in the URL. This avoids browser issues with 401 on
|
|
55
|
+
# the WebSocket handshake and lets long-lived sockets
|
|
56
|
+
# refresh credentials mid-session.
|
|
57
|
+
return f"{self.url.rstrip('/')}/api/v1/socket"
|
|
56
58
|
|
|
57
59
|
async def connect(self):
|
|
58
|
-
"""Establish the persistent websocket connection
|
|
60
|
+
"""Establish the persistent websocket connection and run the
|
|
61
|
+
first-frame auth handshake."""
|
|
59
62
|
if self._connected:
|
|
60
63
|
return
|
|
61
64
|
|
|
65
|
+
if not self.token:
|
|
66
|
+
raise ProtocolException(
|
|
67
|
+
"AsyncSocketClient requires a token for first-frame "
|
|
68
|
+
"auth against /api/v1/socket"
|
|
69
|
+
)
|
|
70
|
+
|
|
62
71
|
ws_url = self._build_ws_url()
|
|
63
72
|
self._connect_cm = websockets.connect(
|
|
64
73
|
ws_url, ping_interval=20, ping_timeout=self.timeout
|
|
65
74
|
)
|
|
66
75
|
self._socket = await self._connect_cm.__aenter__()
|
|
76
|
+
|
|
77
|
+
# First-frame auth: send {"type":"auth","token":"..."} and
|
|
78
|
+
# wait for auth-ok / auth-failed. Run before starting the
|
|
79
|
+
# reader task so the response isn't consumed by the reader's
|
|
80
|
+
# id-based routing.
|
|
81
|
+
await self._socket.send(json.dumps({
|
|
82
|
+
"type": "auth", "token": self.token,
|
|
83
|
+
}))
|
|
84
|
+
try:
|
|
85
|
+
raw = await asyncio.wait_for(
|
|
86
|
+
self._socket.recv(), timeout=self.timeout,
|
|
87
|
+
)
|
|
88
|
+
except asyncio.TimeoutError:
|
|
89
|
+
await self._socket.close()
|
|
90
|
+
raise ProtocolException("Timeout waiting for auth response")
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
resp = json.loads(raw)
|
|
94
|
+
except Exception:
|
|
95
|
+
await self._socket.close()
|
|
96
|
+
raise ProtocolException(
|
|
97
|
+
f"Unexpected non-JSON auth response: {raw!r}"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if resp.get("type") == "auth-ok":
|
|
101
|
+
self.workspace = resp.get("workspace", self.workspace)
|
|
102
|
+
elif resp.get("type") == "auth-failed":
|
|
103
|
+
await self._socket.close()
|
|
104
|
+
raise ProtocolException(
|
|
105
|
+
f"auth failure: {resp.get('error', 'unknown')}"
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
await self._socket.close()
|
|
109
|
+
raise ProtocolException(
|
|
110
|
+
f"Unexpected auth response: {resp!r}"
|
|
111
|
+
)
|
|
112
|
+
|
|
67
113
|
self._connected = True
|
|
68
114
|
self._reader_task = asyncio.create_task(self._reader())
|
|
69
115
|
|
|
@@ -112,10 +112,10 @@ class SocketClient:
|
|
|
112
112
|
return f"ws://{url}"
|
|
113
113
|
|
|
114
114
|
def _build_ws_url(self):
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return
|
|
115
|
+
# /api/v1/socket uses the first-frame auth protocol — the
|
|
116
|
+
# token is sent as the first frame after connecting rather
|
|
117
|
+
# than in the URL.
|
|
118
|
+
return f"{self.url.rstrip('/')}/api/v1/socket"
|
|
119
119
|
|
|
120
120
|
def _get_loop(self):
|
|
121
121
|
"""Get or create the event loop, reusing across calls."""
|
|
@@ -132,15 +132,58 @@ class SocketClient:
|
|
|
132
132
|
return self._loop
|
|
133
133
|
|
|
134
134
|
async def _ensure_connected(self):
|
|
135
|
-
"""Lazily establish the persistent websocket connection
|
|
135
|
+
"""Lazily establish the persistent websocket connection and
|
|
136
|
+
run the first-frame auth handshake."""
|
|
136
137
|
if self._connected:
|
|
137
138
|
return
|
|
138
139
|
|
|
140
|
+
if not self.token:
|
|
141
|
+
raise ProtocolException(
|
|
142
|
+
"SocketClient requires a token for first-frame auth "
|
|
143
|
+
"against /api/v1/socket"
|
|
144
|
+
)
|
|
145
|
+
|
|
139
146
|
ws_url = self._build_ws_url()
|
|
140
147
|
self._connect_cm = websockets.connect(
|
|
141
148
|
ws_url, ping_interval=20, ping_timeout=self.timeout
|
|
142
149
|
)
|
|
143
150
|
self._socket = await self._connect_cm.__aenter__()
|
|
151
|
+
|
|
152
|
+
# First-frame auth — run before starting the reader so the
|
|
153
|
+
# auth-ok / auth-failed response isn't consumed by the reader
|
|
154
|
+
# loop's id-based routing.
|
|
155
|
+
await self._socket.send(json.dumps({
|
|
156
|
+
"type": "auth", "token": self.token,
|
|
157
|
+
}))
|
|
158
|
+
try:
|
|
159
|
+
raw = await asyncio.wait_for(
|
|
160
|
+
self._socket.recv(), timeout=self.timeout,
|
|
161
|
+
)
|
|
162
|
+
except asyncio.TimeoutError:
|
|
163
|
+
await self._socket.close()
|
|
164
|
+
raise ProtocolException("Timeout waiting for auth response")
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
resp = json.loads(raw)
|
|
168
|
+
except Exception:
|
|
169
|
+
await self._socket.close()
|
|
170
|
+
raise ProtocolException(
|
|
171
|
+
f"Unexpected non-JSON auth response: {raw!r}"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if resp.get("type") == "auth-ok":
|
|
175
|
+
self.workspace = resp.get("workspace", self.workspace)
|
|
176
|
+
elif resp.get("type") == "auth-failed":
|
|
177
|
+
await self._socket.close()
|
|
178
|
+
raise ProtocolException(
|
|
179
|
+
f"auth failure: {resp.get('error', 'unknown')}"
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
await self._socket.close()
|
|
183
|
+
raise ProtocolException(
|
|
184
|
+
f"Unexpected auth response: {resp!r}"
|
|
185
|
+
)
|
|
186
|
+
|
|
144
187
|
self._connected = True
|
|
145
188
|
self._reader_task = asyncio.create_task(self._reader())
|
|
146
189
|
|
|
@@ -84,6 +84,18 @@ class ConfigClient(RequestResponse):
|
|
|
84
84
|
)
|
|
85
85
|
return resp.directory
|
|
86
86
|
|
|
87
|
+
async def get_all(self, workspace, timeout=CONFIG_TIMEOUT):
|
|
88
|
+
"""Return every config entry in ``workspace`` as a nested dict
|
|
89
|
+
``{type: {key: value}}``. Values are returned as the raw
|
|
90
|
+
strings stored by config-svc (typically JSON); callers parse
|
|
91
|
+
as needed. An empty dict means the workspace has no config."""
|
|
92
|
+
resp = await self._request(
|
|
93
|
+
operation="config",
|
|
94
|
+
workspace=workspace,
|
|
95
|
+
timeout=timeout,
|
|
96
|
+
)
|
|
97
|
+
return resp.config
|
|
98
|
+
|
|
87
99
|
async def workspaces_for_type(self, type, timeout=CONFIG_TIMEOUT):
|
|
88
100
|
"""Return the set of distinct workspaces with any config of
|
|
89
101
|
the given type."""
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
|
|
2
|
+
from . request_response_spec import RequestResponse, RequestResponseSpec
|
|
3
|
+
from .. schema import (
|
|
4
|
+
IamRequest, IamResponse,
|
|
5
|
+
UserInput, WorkspaceInput, ApiKeyInput,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
IAM_TIMEOUT = 10
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class IamClient(RequestResponse):
|
|
12
|
+
"""Client for the IAM service request/response pub/sub protocol.
|
|
13
|
+
|
|
14
|
+
Mirrors ``ConfigClient``: a thin wrapper around ``RequestResponse``
|
|
15
|
+
that knows the IAM request / response schemas. Only the subset of
|
|
16
|
+
operations actually implemented by the server today has helper
|
|
17
|
+
methods here; callers that need an unimplemented operation can
|
|
18
|
+
build ``IamRequest`` and call ``request()`` directly.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
async def _request(self, timeout=IAM_TIMEOUT, **kwargs):
|
|
22
|
+
resp = await self.request(
|
|
23
|
+
IamRequest(**kwargs),
|
|
24
|
+
timeout=timeout,
|
|
25
|
+
)
|
|
26
|
+
if resp.error:
|
|
27
|
+
raise RuntimeError(
|
|
28
|
+
f"{resp.error.type}: {resp.error.message}"
|
|
29
|
+
)
|
|
30
|
+
return resp
|
|
31
|
+
|
|
32
|
+
async def bootstrap(self, timeout=IAM_TIMEOUT):
|
|
33
|
+
"""Initial-run IAM self-seed. Returns a tuple of
|
|
34
|
+
``(admin_user_id, admin_api_key_plaintext)``. Both are empty
|
|
35
|
+
strings on repeat calls — the operation is a no-op once the
|
|
36
|
+
IAM tables are populated."""
|
|
37
|
+
resp = await self._request(
|
|
38
|
+
operation="bootstrap", timeout=timeout,
|
|
39
|
+
)
|
|
40
|
+
return resp.bootstrap_admin_user_id, resp.bootstrap_admin_api_key
|
|
41
|
+
|
|
42
|
+
async def resolve_api_key(self, api_key, timeout=IAM_TIMEOUT):
|
|
43
|
+
"""Resolve a plaintext API key to its identity triple.
|
|
44
|
+
|
|
45
|
+
Returns ``(user_id, workspace, roles)`` or raises
|
|
46
|
+
``RuntimeError`` with error type ``auth-failed`` if the key is
|
|
47
|
+
unknown / expired / revoked."""
|
|
48
|
+
resp = await self._request(
|
|
49
|
+
operation="resolve-api-key",
|
|
50
|
+
api_key=api_key,
|
|
51
|
+
timeout=timeout,
|
|
52
|
+
)
|
|
53
|
+
return (
|
|
54
|
+
resp.resolved_user_id,
|
|
55
|
+
resp.resolved_workspace,
|
|
56
|
+
list(resp.resolved_roles),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
async def create_user(self, workspace, user, actor="",
|
|
60
|
+
timeout=IAM_TIMEOUT):
|
|
61
|
+
"""Create a user. ``user`` is a ``UserInput``."""
|
|
62
|
+
resp = await self._request(
|
|
63
|
+
operation="create-user",
|
|
64
|
+
workspace=workspace,
|
|
65
|
+
actor=actor,
|
|
66
|
+
user=user,
|
|
67
|
+
timeout=timeout,
|
|
68
|
+
)
|
|
69
|
+
return resp.user
|
|
70
|
+
|
|
71
|
+
async def list_users(self, workspace, actor="", timeout=IAM_TIMEOUT):
|
|
72
|
+
resp = await self._request(
|
|
73
|
+
operation="list-users",
|
|
74
|
+
workspace=workspace,
|
|
75
|
+
actor=actor,
|
|
76
|
+
timeout=timeout,
|
|
77
|
+
)
|
|
78
|
+
return list(resp.users)
|
|
79
|
+
|
|
80
|
+
async def create_api_key(self, workspace, key, actor="",
|
|
81
|
+
timeout=IAM_TIMEOUT):
|
|
82
|
+
"""Create an API key. ``key`` is an ``ApiKeyInput``. Returns
|
|
83
|
+
``(plaintext, record)`` — plaintext is returned once and the
|
|
84
|
+
caller is responsible for surfacing it to the operator."""
|
|
85
|
+
resp = await self._request(
|
|
86
|
+
operation="create-api-key",
|
|
87
|
+
workspace=workspace,
|
|
88
|
+
actor=actor,
|
|
89
|
+
key=key,
|
|
90
|
+
timeout=timeout,
|
|
91
|
+
)
|
|
92
|
+
return resp.api_key_plaintext, resp.api_key
|
|
93
|
+
|
|
94
|
+
async def list_api_keys(self, workspace, user_id, actor="",
|
|
95
|
+
timeout=IAM_TIMEOUT):
|
|
96
|
+
resp = await self._request(
|
|
97
|
+
operation="list-api-keys",
|
|
98
|
+
workspace=workspace,
|
|
99
|
+
actor=actor,
|
|
100
|
+
user_id=user_id,
|
|
101
|
+
timeout=timeout,
|
|
102
|
+
)
|
|
103
|
+
return list(resp.api_keys)
|
|
104
|
+
|
|
105
|
+
async def revoke_api_key(self, workspace, key_id, actor="",
|
|
106
|
+
timeout=IAM_TIMEOUT):
|
|
107
|
+
await self._request(
|
|
108
|
+
operation="revoke-api-key",
|
|
109
|
+
workspace=workspace,
|
|
110
|
+
actor=actor,
|
|
111
|
+
key_id=key_id,
|
|
112
|
+
timeout=timeout,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
async def login(self, username, password, workspace="",
|
|
116
|
+
timeout=IAM_TIMEOUT):
|
|
117
|
+
"""Validate credentials and return ``(jwt, expires_iso)``.
|
|
118
|
+
``workspace`` is optional; defaults at the server to the
|
|
119
|
+
OSS default workspace."""
|
|
120
|
+
resp = await self._request(
|
|
121
|
+
operation="login",
|
|
122
|
+
workspace=workspace,
|
|
123
|
+
username=username,
|
|
124
|
+
password=password,
|
|
125
|
+
timeout=timeout,
|
|
126
|
+
)
|
|
127
|
+
return resp.jwt, resp.jwt_expires
|
|
128
|
+
|
|
129
|
+
async def get_signing_key_public(self, timeout=IAM_TIMEOUT):
|
|
130
|
+
"""Return the active JWT signing public key in PEM. The
|
|
131
|
+
gateway calls this at startup and caches the result."""
|
|
132
|
+
resp = await self._request(
|
|
133
|
+
operation="get-signing-key-public",
|
|
134
|
+
timeout=timeout,
|
|
135
|
+
)
|
|
136
|
+
return resp.signing_key_public
|
|
137
|
+
|
|
138
|
+
async def change_password(self, user_id, current_password,
|
|
139
|
+
new_password, timeout=IAM_TIMEOUT):
|
|
140
|
+
await self._request(
|
|
141
|
+
operation="change-password",
|
|
142
|
+
user_id=user_id,
|
|
143
|
+
password=current_password,
|
|
144
|
+
new_password=new_password,
|
|
145
|
+
timeout=timeout,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
async def reset_password(self, workspace, user_id, actor="",
|
|
149
|
+
timeout=IAM_TIMEOUT):
|
|
150
|
+
"""Admin-driven password reset. Returns the plaintext
|
|
151
|
+
temporary password (returned once)."""
|
|
152
|
+
resp = await self._request(
|
|
153
|
+
operation="reset-password",
|
|
154
|
+
workspace=workspace,
|
|
155
|
+
actor=actor,
|
|
156
|
+
user_id=user_id,
|
|
157
|
+
timeout=timeout,
|
|
158
|
+
)
|
|
159
|
+
return resp.temporary_password
|
|
160
|
+
|
|
161
|
+
async def get_user(self, workspace, user_id, actor="",
|
|
162
|
+
timeout=IAM_TIMEOUT):
|
|
163
|
+
resp = await self._request(
|
|
164
|
+
operation="get-user",
|
|
165
|
+
workspace=workspace,
|
|
166
|
+
actor=actor,
|
|
167
|
+
user_id=user_id,
|
|
168
|
+
timeout=timeout,
|
|
169
|
+
)
|
|
170
|
+
return resp.user
|
|
171
|
+
|
|
172
|
+
async def update_user(self, workspace, user_id, user, actor="",
|
|
173
|
+
timeout=IAM_TIMEOUT):
|
|
174
|
+
resp = await self._request(
|
|
175
|
+
operation="update-user",
|
|
176
|
+
workspace=workspace,
|
|
177
|
+
actor=actor,
|
|
178
|
+
user_id=user_id,
|
|
179
|
+
user=user,
|
|
180
|
+
timeout=timeout,
|
|
181
|
+
)
|
|
182
|
+
return resp.user
|
|
183
|
+
|
|
184
|
+
async def disable_user(self, workspace, user_id, actor="",
|
|
185
|
+
timeout=IAM_TIMEOUT):
|
|
186
|
+
await self._request(
|
|
187
|
+
operation="disable-user",
|
|
188
|
+
workspace=workspace,
|
|
189
|
+
actor=actor,
|
|
190
|
+
user_id=user_id,
|
|
191
|
+
timeout=timeout,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
async def enable_user(self, workspace, user_id, actor="",
|
|
195
|
+
timeout=IAM_TIMEOUT):
|
|
196
|
+
await self._request(
|
|
197
|
+
operation="enable-user",
|
|
198
|
+
workspace=workspace,
|
|
199
|
+
actor=actor,
|
|
200
|
+
user_id=user_id,
|
|
201
|
+
timeout=timeout,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
async def delete_user(self, workspace, user_id, actor="",
|
|
205
|
+
timeout=IAM_TIMEOUT):
|
|
206
|
+
await self._request(
|
|
207
|
+
operation="delete-user",
|
|
208
|
+
workspace=workspace,
|
|
209
|
+
actor=actor,
|
|
210
|
+
user_id=user_id,
|
|
211
|
+
timeout=timeout,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
async def create_workspace(self, workspace_record, actor="",
|
|
215
|
+
timeout=IAM_TIMEOUT):
|
|
216
|
+
resp = await self._request(
|
|
217
|
+
operation="create-workspace",
|
|
218
|
+
actor=actor,
|
|
219
|
+
workspace_record=workspace_record,
|
|
220
|
+
timeout=timeout,
|
|
221
|
+
)
|
|
222
|
+
return resp.workspace
|
|
223
|
+
|
|
224
|
+
async def list_workspaces(self, actor="", timeout=IAM_TIMEOUT):
|
|
225
|
+
resp = await self._request(
|
|
226
|
+
operation="list-workspaces",
|
|
227
|
+
actor=actor,
|
|
228
|
+
timeout=timeout,
|
|
229
|
+
)
|
|
230
|
+
return list(resp.workspaces)
|
|
231
|
+
|
|
232
|
+
async def get_workspace(self, workspace_id, actor="",
|
|
233
|
+
timeout=IAM_TIMEOUT):
|
|
234
|
+
from ..schema import WorkspaceInput
|
|
235
|
+
resp = await self._request(
|
|
236
|
+
operation="get-workspace",
|
|
237
|
+
actor=actor,
|
|
238
|
+
workspace_record=WorkspaceInput(id=workspace_id),
|
|
239
|
+
timeout=timeout,
|
|
240
|
+
)
|
|
241
|
+
return resp.workspace
|
|
242
|
+
|
|
243
|
+
async def update_workspace(self, workspace_record, actor="",
|
|
244
|
+
timeout=IAM_TIMEOUT):
|
|
245
|
+
resp = await self._request(
|
|
246
|
+
operation="update-workspace",
|
|
247
|
+
actor=actor,
|
|
248
|
+
workspace_record=workspace_record,
|
|
249
|
+
timeout=timeout,
|
|
250
|
+
)
|
|
251
|
+
return resp.workspace
|
|
252
|
+
|
|
253
|
+
async def disable_workspace(self, workspace_id, actor="",
|
|
254
|
+
timeout=IAM_TIMEOUT):
|
|
255
|
+
from ..schema import WorkspaceInput
|
|
256
|
+
await self._request(
|
|
257
|
+
operation="disable-workspace",
|
|
258
|
+
actor=actor,
|
|
259
|
+
workspace_record=WorkspaceInput(id=workspace_id),
|
|
260
|
+
timeout=timeout,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
async def rotate_signing_key(self, actor="", timeout=IAM_TIMEOUT):
|
|
264
|
+
await self._request(
|
|
265
|
+
operation="rotate-signing-key",
|
|
266
|
+
actor=actor,
|
|
267
|
+
timeout=timeout,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class IamClientSpec(RequestResponseSpec):
|
|
272
|
+
def __init__(self, request_name, response_name):
|
|
273
|
+
super().__init__(
|
|
274
|
+
request_name=request_name,
|
|
275
|
+
request_schema=IamRequest,
|
|
276
|
+
response_name=response_name,
|
|
277
|
+
response_schema=IamResponse,
|
|
278
|
+
impl=IamClient,
|
|
279
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.4.5"
|
|
@@ -15,6 +15,7 @@ from .translators.library import LibraryRequestTranslator, LibraryResponseTransl
|
|
|
15
15
|
from .translators.document_loading import DocumentTranslator, TextDocumentTranslator
|
|
16
16
|
from .translators.config import ConfigRequestTranslator, ConfigResponseTranslator
|
|
17
17
|
from .translators.flow import FlowRequestTranslator, FlowResponseTranslator
|
|
18
|
+
from .translators.iam import IamRequestTranslator, IamResponseTranslator
|
|
18
19
|
from .translators.prompt import PromptRequestTranslator, PromptResponseTranslator
|
|
19
20
|
from .translators.tool import ToolRequestTranslator, ToolResponseTranslator
|
|
20
21
|
from .translators.embeddings_query import (
|
|
@@ -85,11 +86,17 @@ TranslatorRegistry.register_service(
|
|
|
85
86
|
)
|
|
86
87
|
|
|
87
88
|
TranslatorRegistry.register_service(
|
|
88
|
-
"flow",
|
|
89
|
-
FlowRequestTranslator(),
|
|
89
|
+
"flow",
|
|
90
|
+
FlowRequestTranslator(),
|
|
90
91
|
FlowResponseTranslator()
|
|
91
92
|
)
|
|
92
93
|
|
|
94
|
+
TranslatorRegistry.register_service(
|
|
95
|
+
"iam",
|
|
96
|
+
IamRequestTranslator(),
|
|
97
|
+
IamResponseTranslator()
|
|
98
|
+
)
|
|
99
|
+
|
|
93
100
|
TranslatorRegistry.register_service(
|
|
94
101
|
"prompt",
|
|
95
102
|
PromptRequestTranslator(),
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from typing import Dict, Any, Tuple
|
|
2
|
+
|
|
3
|
+
from ...schema import IamRequest, IamResponse
|
|
4
|
+
from ...schema import (
|
|
5
|
+
UserInput, UserRecord,
|
|
6
|
+
WorkspaceInput, WorkspaceRecord,
|
|
7
|
+
ApiKeyInput, ApiKeyRecord,
|
|
8
|
+
)
|
|
9
|
+
from .base import MessageTranslator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _user_input_from_dict(d):
|
|
13
|
+
if d is None:
|
|
14
|
+
return None
|
|
15
|
+
return UserInput(
|
|
16
|
+
username=d.get("username", ""),
|
|
17
|
+
name=d.get("name", ""),
|
|
18
|
+
email=d.get("email", ""),
|
|
19
|
+
password=d.get("password", ""),
|
|
20
|
+
roles=list(d.get("roles", [])),
|
|
21
|
+
enabled=d.get("enabled", True),
|
|
22
|
+
must_change_password=d.get("must_change_password", False),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _workspace_input_from_dict(d):
|
|
27
|
+
if d is None:
|
|
28
|
+
return None
|
|
29
|
+
return WorkspaceInput(
|
|
30
|
+
id=d.get("id", ""),
|
|
31
|
+
name=d.get("name", ""),
|
|
32
|
+
enabled=d.get("enabled", True),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _api_key_input_from_dict(d):
|
|
37
|
+
if d is None:
|
|
38
|
+
return None
|
|
39
|
+
return ApiKeyInput(
|
|
40
|
+
user_id=d.get("user_id", ""),
|
|
41
|
+
name=d.get("name", ""),
|
|
42
|
+
expires=d.get("expires", ""),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _user_record_to_dict(r):
|
|
47
|
+
if r is None:
|
|
48
|
+
return None
|
|
49
|
+
return {
|
|
50
|
+
"id": r.id,
|
|
51
|
+
"workspace": r.workspace,
|
|
52
|
+
"username": r.username,
|
|
53
|
+
"name": r.name,
|
|
54
|
+
"email": r.email,
|
|
55
|
+
"roles": list(r.roles),
|
|
56
|
+
"enabled": r.enabled,
|
|
57
|
+
"must_change_password": r.must_change_password,
|
|
58
|
+
"created": r.created,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _workspace_record_to_dict(r):
|
|
63
|
+
if r is None:
|
|
64
|
+
return None
|
|
65
|
+
return {
|
|
66
|
+
"id": r.id,
|
|
67
|
+
"name": r.name,
|
|
68
|
+
"enabled": r.enabled,
|
|
69
|
+
"created": r.created,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _api_key_record_to_dict(r):
|
|
74
|
+
if r is None:
|
|
75
|
+
return None
|
|
76
|
+
return {
|
|
77
|
+
"id": r.id,
|
|
78
|
+
"user_id": r.user_id,
|
|
79
|
+
"name": r.name,
|
|
80
|
+
"prefix": r.prefix,
|
|
81
|
+
"expires": r.expires,
|
|
82
|
+
"created": r.created,
|
|
83
|
+
"last_used": r.last_used,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class IamRequestTranslator(MessageTranslator):
|
|
88
|
+
|
|
89
|
+
def decode(self, data: Dict[str, Any]) -> IamRequest:
|
|
90
|
+
return IamRequest(
|
|
91
|
+
operation=data.get("operation", ""),
|
|
92
|
+
workspace=data.get("workspace", ""),
|
|
93
|
+
actor=data.get("actor", ""),
|
|
94
|
+
user_id=data.get("user_id", ""),
|
|
95
|
+
username=data.get("username", ""),
|
|
96
|
+
key_id=data.get("key_id", ""),
|
|
97
|
+
api_key=data.get("api_key", ""),
|
|
98
|
+
password=data.get("password", ""),
|
|
99
|
+
new_password=data.get("new_password", ""),
|
|
100
|
+
user=_user_input_from_dict(data.get("user")),
|
|
101
|
+
workspace_record=_workspace_input_from_dict(
|
|
102
|
+
data.get("workspace_record")
|
|
103
|
+
),
|
|
104
|
+
key=_api_key_input_from_dict(data.get("key")),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def encode(self, obj: IamRequest) -> Dict[str, Any]:
|
|
108
|
+
result = {"operation": obj.operation}
|
|
109
|
+
for fname in (
|
|
110
|
+
"workspace", "actor", "user_id", "username", "key_id",
|
|
111
|
+
"api_key", "password", "new_password",
|
|
112
|
+
):
|
|
113
|
+
v = getattr(obj, fname, "")
|
|
114
|
+
if v:
|
|
115
|
+
result[fname] = v
|
|
116
|
+
if obj.user is not None:
|
|
117
|
+
result["user"] = {
|
|
118
|
+
"username": obj.user.username,
|
|
119
|
+
"name": obj.user.name,
|
|
120
|
+
"email": obj.user.email,
|
|
121
|
+
"password": obj.user.password,
|
|
122
|
+
"roles": list(obj.user.roles),
|
|
123
|
+
"enabled": obj.user.enabled,
|
|
124
|
+
"must_change_password": obj.user.must_change_password,
|
|
125
|
+
}
|
|
126
|
+
if obj.workspace_record is not None:
|
|
127
|
+
result["workspace_record"] = {
|
|
128
|
+
"id": obj.workspace_record.id,
|
|
129
|
+
"name": obj.workspace_record.name,
|
|
130
|
+
"enabled": obj.workspace_record.enabled,
|
|
131
|
+
}
|
|
132
|
+
if obj.key is not None:
|
|
133
|
+
result["key"] = {
|
|
134
|
+
"user_id": obj.key.user_id,
|
|
135
|
+
"name": obj.key.name,
|
|
136
|
+
"expires": obj.key.expires,
|
|
137
|
+
}
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class IamResponseTranslator(MessageTranslator):
|
|
142
|
+
|
|
143
|
+
def decode(self, data: Dict[str, Any]) -> IamResponse:
|
|
144
|
+
raise NotImplementedError(
|
|
145
|
+
"IamResponse is a server-produced message; no HTTP→schema "
|
|
146
|
+
"path is needed"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def encode(self, obj: IamResponse) -> Dict[str, Any]:
|
|
150
|
+
result: Dict[str, Any] = {}
|
|
151
|
+
|
|
152
|
+
if obj.user is not None:
|
|
153
|
+
result["user"] = _user_record_to_dict(obj.user)
|
|
154
|
+
if obj.users:
|
|
155
|
+
result["users"] = [_user_record_to_dict(u) for u in obj.users]
|
|
156
|
+
if obj.workspace is not None:
|
|
157
|
+
result["workspace"] = _workspace_record_to_dict(obj.workspace)
|
|
158
|
+
if obj.workspaces:
|
|
159
|
+
result["workspaces"] = [
|
|
160
|
+
_workspace_record_to_dict(w) for w in obj.workspaces
|
|
161
|
+
]
|
|
162
|
+
if obj.api_key_plaintext:
|
|
163
|
+
result["api_key_plaintext"] = obj.api_key_plaintext
|
|
164
|
+
if obj.api_key is not None:
|
|
165
|
+
result["api_key"] = _api_key_record_to_dict(obj.api_key)
|
|
166
|
+
if obj.api_keys:
|
|
167
|
+
result["api_keys"] = [
|
|
168
|
+
_api_key_record_to_dict(k) for k in obj.api_keys
|
|
169
|
+
]
|
|
170
|
+
if obj.jwt:
|
|
171
|
+
result["jwt"] = obj.jwt
|
|
172
|
+
if obj.jwt_expires:
|
|
173
|
+
result["jwt_expires"] = obj.jwt_expires
|
|
174
|
+
if obj.signing_key_public:
|
|
175
|
+
result["signing_key_public"] = obj.signing_key_public
|
|
176
|
+
if obj.resolved_user_id:
|
|
177
|
+
result["resolved_user_id"] = obj.resolved_user_id
|
|
178
|
+
if obj.resolved_workspace:
|
|
179
|
+
result["resolved_workspace"] = obj.resolved_workspace
|
|
180
|
+
if obj.resolved_roles:
|
|
181
|
+
result["resolved_roles"] = list(obj.resolved_roles)
|
|
182
|
+
if obj.temporary_password:
|
|
183
|
+
result["temporary_password"] = obj.temporary_password
|
|
184
|
+
if obj.bootstrap_admin_user_id:
|
|
185
|
+
result["bootstrap_admin_user_id"] = obj.bootstrap_admin_user_id
|
|
186
|
+
if obj.bootstrap_admin_api_key:
|
|
187
|
+
result["bootstrap_admin_api_key"] = obj.bootstrap_admin_api_key
|
|
188
|
+
|
|
189
|
+
return result
|
|
190
|
+
|
|
191
|
+
def encode_with_completion(
|
|
192
|
+
self, obj: IamResponse,
|
|
193
|
+
) -> Tuple[Dict[str, Any], bool]:
|
|
194
|
+
return self.encode(obj), True
|