Skip to content

Commit

Permalink
🎨 Update trust registry models (#808)
Browse files Browse the repository at this point in the history
* 🎨 TrustRegistry: replace TypedDict models with pydantic BaseModel

* 🎨 improve error handling

* 🎨 add TrustRegistryRole type

* ✅ Update tests to use new models instead of dictionaries

* 🎨 fix validating json response

* 🎨 improve error handling

* ✅ fix TR service tests

* ✅ fix test
  • Loading branch information
ff137 authored May 17, 2024
1 parent b3488c0 commit 5d20132
Show file tree
Hide file tree
Showing 22 changed files with 196 additions and 248 deletions.
2 changes: 1 addition & 1 deletion app/models/tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from aries_cloudcontroller import CreateWalletRequest, UpdateWalletRequest
from pydantic import BaseModel, Field, field_validator

from app.models.trust_registry import TrustRegistryRole
from shared.exceptions import CloudApiValueError
from shared.models.trustregistry import TrustRegistryRole

# Deduplicate some descriptions and field definitions
allowable_special_chars = ".!@$*()~_-" # the dash character must be at the end, otherwise it defines a regex range
Expand Down
20 changes: 0 additions & 20 deletions app/models/trust_registry.py

This file was deleted.

2 changes: 1 addition & 1 deletion app/routes/admin/tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
TenantAuth,
UpdateTenantRequest,
)
from app.models.trust_registry import Actor
from app.services.onboarding.tenants import handle_tenant_update, onboard_tenant
from app.services.trust_registry.actors import (
fetch_actor_by_id,
Expand All @@ -39,6 +38,7 @@
tenant_from_wallet_record,
)
from shared.log_config import get_logger
from shared.models.trustregistry import Actor

logger = get_logger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion app/routes/trust_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import app.services.trust_registry.actors as registry_actors
import app.services.trust_registry.schemas as registry_schemas
from app.models.trust_registry import Actor, Schema
from shared.log_config import get_logger
from shared.models.trustregistry import Actor, Schema

logger = get_logger(__name__)

Expand Down
17 changes: 9 additions & 8 deletions app/services/onboarding/tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
handle_model_with_validation,
)
from app.models.tenants import OnboardResult, UpdateTenantRequest
from app.models.trust_registry import TrustRegistryRole
from app.services.onboarding.issuer import onboard_issuer
from app.services.onboarding.verifier import onboard_verifier
from app.services.trust_registry.actors import fetch_actor_by_id, update_actor
from shared.log_config import get_logger
from shared.models.trustregistry import TrustRegistryRole

logger = get_logger(__name__)

Expand Down Expand Up @@ -47,14 +47,13 @@ async def handle_tenant_update(
)

if actor:
existing_roles = actor["roles"]
existing_roles = actor.roles
added_roles = list(set(new_roles) - set(existing_roles))

if new_label or added_roles: # Only update actor if
updated_actor = actor.copy()

update_dict = {}
if new_label:
updated_actor["name"] = new_label
update_dict["name"] = new_label

if added_roles:
bound_logger.info("Updating tenant roles")
Expand All @@ -73,9 +72,11 @@ async def handle_tenant_update(
)

# Remove duplicates from the role list
updated_actor["roles"] = list(set(new_roles + existing_roles))
updated_actor["did"] = onboard_result.did
updated_actor["didcomm_invitation"] = onboard_result.didcomm_invitation
update_dict["roles"] = list(set(new_roles + existing_roles))
update_dict["did"] = onboard_result.did
update_dict["didcomm_invitation"] = onboard_result.didcomm_invitation

updated_actor = actor.model_copy(update=update_dict)

await update_actor(updated_actor)

Expand Down
19 changes: 10 additions & 9 deletions app/services/trust_registry/actors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import List, Optional

from app.exceptions import TrustRegistryException
from app.models.trust_registry import Actor, TrustRegistryRole
from shared.constants import TRUST_REGISTRY_URL
from shared.log_config import get_logger
from shared.models.trustregistry import Actor, TrustRegistryRole
from shared.util.rich_async_client import RichAsyncClient

logger = get_logger(__name__)
Expand All @@ -22,7 +22,7 @@ async def register_actor(actor: Actor) -> None:
bound_logger.info("Registering actor on trust registry")
async with RichAsyncClient(raise_status_error=False) as client:
actor_response = await client.post(
f"{TRUST_REGISTRY_URL}/registry/actors", json=actor
f"{TRUST_REGISTRY_URL}/registry/actors", json=actor.model_dump()
)

if actor_response.status_code == 422:
Expand Down Expand Up @@ -53,7 +53,8 @@ async def update_actor(actor: Actor) -> None:
bound_logger.info("Updating actor on trust registry")
async with RichAsyncClient(raise_status_error=False) as client:
update_response = await client.put(
f"{TRUST_REGISTRY_URL}/registry/actors/{actor['id']}", json=actor
f"{TRUST_REGISTRY_URL}/registry/actors/{actor.id}",
json=actor.model_dump(),
)

if update_response.status_code == 422:
Expand Down Expand Up @@ -101,7 +102,7 @@ async def fetch_all_actors() -> List[Actor]:
actors_response.status_code,
)

actors = actors_response.json()
actors = [Actor.model_validate(actor) for actor in actors_response.json()]

if actors:
logger.info("Successfully got all actors.")
Expand Down Expand Up @@ -145,7 +146,7 @@ async def fetch_actor_by_did(did: str) -> Optional[Actor]:
)

bound_logger.info("Successfully fetched actor from trust registry.")
return actor_response.json()
return Actor.model_validate(actor_response.json())


async def fetch_actor_by_id(actor_id: str) -> Optional[Actor]:
Expand Down Expand Up @@ -182,7 +183,7 @@ async def fetch_actor_by_id(actor_id: str) -> Optional[Actor]:
)

bound_logger.info("Successfully fetched actor from trust registry.")
return actor_response.json()
return Actor.model_validate(actor_response.json())


async def fetch_actor_by_name(actor_name: str) -> Optional[Actor]:
Expand Down Expand Up @@ -219,7 +220,7 @@ async def fetch_actor_by_name(actor_name: str) -> Optional[Actor]:
)

bound_logger.info("Successfully fetched actor from trust registry.")
return actor_response.json()
return Actor.model_validate(actor_response.json())


async def fetch_actors_with_role(role: TrustRegistryRole) -> List[Actor]:
Expand Down Expand Up @@ -250,8 +251,8 @@ async def fetch_actors_with_role(role: TrustRegistryRole) -> List[Actor]:
actors_response.status_code,
)

actors = actors_response.json()
actors_with_role_list = [actor for actor in actors if role in actor["roles"]]
actors = [Actor.model_validate(actor) for actor in actors_response.json()]
actors_with_role_list = [actor for actor in actors if role in actor.roles]

if actors_with_role_list:
bound_logger.info("Successfully got actors with requested role.")
Expand Down
6 changes: 3 additions & 3 deletions app/services/trust_registry/schemas.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import List, Optional

from app.exceptions import TrustRegistryException
from app.models.trust_registry import Schema
from shared.constants import TRUST_REGISTRY_URL
from shared.log_config import get_logger
from shared.models.trustregistry import Schema
from shared.util.rich_async_client import RichAsyncClient

logger = get_logger(__name__)
Expand Down Expand Up @@ -62,7 +62,7 @@ async def fetch_schemas() -> List[Schema]:
f"Unable to fetch schemas: `{schemas_res.text}`.", schemas_res.status_code
)

result = schemas_res.json()
result = [Schema.model_validate(schema) for schema in schemas_res.json()]
logger.info("Successfully fetched schemas from trust registry.")
return result

Expand Down Expand Up @@ -98,7 +98,7 @@ async def get_schema_by_id(schema_id: str) -> Optional[Schema]:
schema_response.status_code,
)

result = schema_response.json()
result = Schema.model_validate(schema_response.json())
logger.info("Successfully fetched schema from trust registry.")
return result

Expand Down
4 changes: 2 additions & 2 deletions app/services/trust_registry/util/actor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from app.exceptions import TrustRegistryException
from app.models.trust_registry import TrustRegistryRole
from app.services.trust_registry.actors import fetch_actor_by_id
from shared.constants import TRUST_REGISTRY_URL
from shared.log_config import get_logger
from shared.models.trustregistry import TrustRegistryRole
from shared.util.rich_async_client import RichAsyncClient

logger = get_logger(__name__)
Expand All @@ -26,7 +26,7 @@ async def actor_has_role(actor_id: str, role: TrustRegistryRole) -> bool:
bound_logger.info("Actor not registered in trust registry.")
raise TrustRegistryException(f"Actor with id {actor_id} not found.", 404)

result = bool(role in actor["roles"])
result = role in actor.roles
if result:
bound_logger.info("Actor has requested role.")
else:
Expand Down
4 changes: 2 additions & 2 deletions app/services/trust_registry/util/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ async def assert_valid_issuer(did: str, schema_id: Optional[str] = None) -> None
bound_logger.info("DID not registered in the trust registry.")
raise TrustRegistryException(f"DID {did} not registered in the trust registry.")

if "issuer" not in actor["roles"]:
if "issuer" not in actor.roles:
bound_logger.info("Actor associated with DID does not have `issuer` role.")
raise TrustRegistryException(
f"Actor {actor['id']} does not have required role 'issuer'."
f"Actor {actor.id} does not have required role 'issuer'."
)
bound_logger.info("Issuer DID is valid")

Expand Down
6 changes: 3 additions & 3 deletions app/tests/e2e/test_tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,10 @@ async def test_update_tenant_verifier_to_issuer(

assert new_actor
assert_that(new_actor).has_name(new_wallet_label)
assert_that(new_actor).has_did(f"{new_actor['did']}")
assert_that(new_actor["roles"]).contains_only("issuer", "verifier")
assert_that(new_actor).has_did(new_actor.did)
assert_that(new_actor.roles).contains_only("issuer", "verifier")

assert new_actor["didcomm_invitation"] is not None
assert new_actor.didcomm_invitation is not None


@pytest.mark.anyio
Expand Down
4 changes: 2 additions & 2 deletions app/tests/e2e/verifier/test_verifier_oob.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ async def test_accept_proof_request_verifier_oob_connection(
verifier_actor = await fetch_actor_by_id(acme_wallet_id)

assert verifier_actor
assert verifier_actor["didcomm_invitation"]
assert verifier_actor.didcomm_invitation

invitation_json = base64_to_json(
verifier_actor["didcomm_invitation"].split("?oob=")[1]
verifier_actor.didcomm_invitation.split("?oob=")[1]
)
invitation_response = (
await alice_member_client.post(
Expand Down
2 changes: 1 addition & 1 deletion app/tests/routes/admin_tenants/test_create_tenant.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
CreateWalletRequestWithGroups,
OnboardResult,
)
from app.models.trust_registry import Actor
from app.routes.admin.tenants import create_tenant
from shared.models.trustregistry import Actor

wallet_id = "some_wallet_id"
wallet_name = "some_wallet_name"
Expand Down
Loading

0 comments on commit 5d20132

Please sign in to comment.