-
Notifications
You must be signed in to change notification settings - Fork 9
/
tenants.py
143 lines (122 loc) · 5.3 KB
/
tenants.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from typing import List
from aries_cloudcontroller import AcaPyClient, UpdateWalletRequest, WalletRecord
from fastapi.exceptions import HTTPException
from app.dependencies.acapy_clients import (
get_governance_controller,
get_tenant_controller,
)
from app.exceptions import (
CloudApiException,
handle_acapy_call,
handle_model_with_validation,
)
from app.models.tenants import OnboardResult, UpdateTenantRequest
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__)
async def handle_tenant_update(
admin_controller: AcaPyClient,
wallet_id: str,
update_request: UpdateTenantRequest,
) -> WalletRecord:
bound_logger = logger.bind(body={"wallet_id": wallet_id})
bound_logger.bind(body=update_request).debug("Handling tenant update")
new_roles = update_request.roles or []
new_label = update_request.wallet_label
new_image_url = update_request.image_url
# See if this wallet belongs to an actor
actor = await fetch_actor_by_id(wallet_id)
if not actor and new_roles:
bound_logger.info(
"Bad request: Tenant not found in trust registry. "
"Holder tenants cannot be updated with new roles."
)
raise HTTPException(
409,
"Holder tenants cannot be updated with new roles. "
"Only existing issuers or verifiers can have their role updated.",
)
if actor:
existing_roles = actor.roles
existing_image_url = actor.image_url
added_roles = list(set(new_roles) - set(existing_roles))
if new_label or added_roles or new_image_url: # Only update actor if
update_dict = {}
if new_label:
update_dict["name"] = new_label
if added_roles:
bound_logger.info("Updating tenant roles")
# We need to pose as the tenant to onboard for the specified role
token_response = await handle_acapy_call(
logger=bound_logger,
acapy_call=admin_controller.multitenancy.get_auth_token,
wallet_id=wallet_id,
)
onboard_result = await onboard_tenant(
tenant_label=new_label,
roles=added_roles,
wallet_auth_token=token_response.token,
wallet_id=wallet_id,
)
# Remove duplicates from the role list
update_dict["roles"] = list(set(new_roles + existing_roles))
update_dict["did"] = onboard_result.did
update_dict["didcomm_invitation"] = onboard_result.didcomm_invitation
if new_image_url and new_image_url != existing_image_url:
update_dict["image_url"] = new_image_url
updated_actor = actor.model_copy(update=update_dict)
await update_actor(updated_actor)
bound_logger.debug("Updating wallet")
request_body = handle_model_with_validation(
logger=bound_logger,
model_class=UpdateWalletRequest,
label=new_label,
image_url=update_request.image_url,
extra_settings=update_request.extra_settings,
)
wallet = await handle_acapy_call(
logger=bound_logger,
acapy_call=admin_controller.multitenancy.update_wallet,
wallet_id=wallet_id,
body=request_body,
)
bound_logger.debug("Tenant update handled successfully.")
return wallet
async def onboard_tenant(
*,
tenant_label: str,
roles: List[TrustRegistryRole],
wallet_auth_token: str,
wallet_id: str,
) -> OnboardResult:
bound_logger = logger.bind(
body={"tenant_label": tenant_label, "roles": roles, "wallet_id": wallet_id}
)
bound_logger.bind(body=roles).debug("Start onboarding tenant")
if "issuer" in roles:
bound_logger.debug("Tenant has 'issuer' role, onboarding as issuer")
# Get governance and tenant controllers, onboard issuer
async with get_governance_controller() as governance_controller, get_tenant_controller(
wallet_auth_token
) as tenant_controller:
onboard_result = await onboard_issuer(
endorser_controller=governance_controller,
issuer_controller=tenant_controller,
issuer_wallet_id=wallet_id,
issuer_label=tenant_label,
)
bound_logger.debug("Onboarding as issuer completed successfully.")
return onboard_result
elif "verifier" in roles:
bound_logger.debug("Tenant has 'verifier' role, onboarding as verifier")
async with get_tenant_controller(wallet_auth_token) as tenant_controller:
onboard_result = await onboard_verifier(
verifier_label=tenant_label, verifier_controller=tenant_controller
)
bound_logger.debug("Onboarding as verifier completed successfully.")
return onboard_result
bound_logger.error("Tenant request does not have valid role(s) for onboarding.")
raise CloudApiException("Unable to onboard tenant without role(s).")