-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathschema_publisher.py
125 lines (112 loc) · 5.25 KB
/
schema_publisher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from logging import Logger
from typing import List
from aries_cloudcontroller import AcaPyClient, SchemaGetResult, SchemaSendRequest
from app.exceptions import CloudApiException, TrustRegistryException, handle_acapy_call
from app.models.definitions import CreateSchema
from app.services.trust_registry.schemas import register_schema
from app.util.definitions import credential_schema_from_acapy
class SchemaPublisher:
def __init__(
self,
controller: AcaPyClient,
logger: Logger,
):
self._logger = logger
self._controller = controller
async def publish_schema(self, schema_request: SchemaSendRequest):
result = await handle_acapy_call(
logger=self._logger,
acapy_call=self._controller.schema.publish_schema,
body=schema_request,
create_transaction_for_endorser=False,
)
return result
async def handle_existing_schema(self, schema: CreateSchema):
self._logger.info("Handling case of schema already existing on ledger")
self._logger.debug("Fetching public DID for governance controller")
pub_did = await handle_acapy_call(
logger=self._logger,
acapy_call=self._controller.wallet.get_public_did,
)
_schema_id = f"{pub_did.result.did}:2:{schema.name}:{schema.version}"
self._logger.debug(
"Fetching schema id `{}` which is associated with request",
_schema_id,
)
_schema: SchemaGetResult = await handle_acapy_call(
logger=self._logger,
acapy_call=self._controller.schema.get_schema,
schema_id=_schema_id,
)
# Edge case where the governance agent has changed its public did
# Then we need to retrieve the schema in a different way as constructing the schema ID the way above
# will not be correct due to different public did.
if _schema.var_schema is None:
self._logger.debug(
"Schema not found. Governance agent may have changed public DID. "
"Fetching schemas created by governance agent with request name and version"
)
schemas_created_ids = await handle_acapy_call(
logger=self._logger,
acapy_call=self._controller.schema.get_created_schemas,
schema_name=schema.name,
schema_version=schema.version,
)
self._logger.debug("Getting schemas associated with fetched ids")
schemas: List[SchemaGetResult] = [
await handle_acapy_call(
logger=self._logger,
acapy_call=self._controller.schema.get_schema,
schema_id=schema_id,
)
for schema_id in schemas_created_ids.schema_ids
if schema_id
]
if schemas:
if len(schemas) > 1:
raise CloudApiException( # pylint: disable=W0707
f"Multiple schemas with name {schema.name} and version {schema.version} exist."
+ f"These are: `{str(schemas_created_ids.schema_ids)}`.",
409,
)
self._logger.debug("Using updated schema id with new DID")
_schema: SchemaGetResult = schemas[0]
else:
# if schema already exists, we should at least fetch 1, so this should never happen
raise CloudApiException(
"Could not publish schema.", 500
) # pylint: disable=W0707
# Schema exists with different attributes
if set(_schema.var_schema.attr_names) != set(schema.attribute_names):
raise CloudApiException(
"Error creating schema: Schema already exists with different attribute names."
+ f"Given: `{str(set(_schema.var_schema.attr_names))}`. "
f"Found: `{str(set(schema.attribute_names))}`.",
409,
) # pylint: disable=W0707
result = credential_schema_from_acapy(_schema.var_schema)
self._logger.info(
"Schema already exists on ledger. Returning schema definition: `{}`.",
result,
)
return result
async def register_schema(self, schema_id: str):
self._logger.debug("Registering schema after successful publish to ledger")
try:
await register_schema(schema_id=schema_id)
except TrustRegistryException as error:
# If status_code is 405 it means the schema already exists in the trust registry
# That's okay, because we've achieved our intended result:
# make sure the schema is registered in the trust registry
self._logger.info(
"Caught TrustRegistryException when registering schema. "
"Got status code {} with message `{}`",
error.status_code,
error.detail,
)
if error.status_code == 405:
self._logger.info(
"Status code 405 indicates schema is already registered, so we can continue"
)
else:
raise error